Skip to content

Commit ae3da40

Browse files
authored
Merge pull request #43 from DigitalPebble/1
Initial version of website with GitHub pages
2 parents d0d82dd + a7de49f commit ae3da40

12 files changed

Lines changed: 342 additions & 1 deletion

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Deploy documentation to GH pages
2+
on:
3+
push:
4+
branches:
5+
- main
6+
7+
jobs:
8+
deploy:
9+
runs-on: carbonrunner-4vcpu-ubuntu-latest
10+
permissions:
11+
contents: write # To push a branch
12+
pages: write # To push to a GitHub Pages site
13+
id-token: write # To update the deployment status
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
- name: Install latest mdbook
19+
run: |
20+
tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name')
21+
url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz"
22+
mkdir mdbook
23+
curl -sSL $url | tar -xz --directory=./mdbook
24+
echo `pwd`/mdbook >> $GITHUB_PATH
25+
- name: Build Book
26+
run: |
27+
cd docs
28+
mdbook build
29+
- name: Setup Pages
30+
uses: actions/configure-pages@v4
31+
- name: Upload artifact
32+
uses: actions/upload-pages-artifact@v3
33+
with:
34+
# Upload entire repository
35+
path: 'docs/book'
36+
- name: Deploy to GitHub Pages
37+
id: deployment
38+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ target/
1212

1313
# avoid accidental addition of dirs mentioned in README
1414
curs/
15-
output/
15+
output/
16+
17+
docs/book

docs/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The documentation is built with [mdbook](https://rust-lang.github.io/mdBook/guide/installation.html).
2+
3+
To build the documentation, install _mdbook_ and run
4+
5+
`mdbook build`
6+
7+
This generates the HTML code in the directory _book_.
8+
9+
The content will be organised following the
10+
documentation system :
11+
12+
https://docs.divio.com/documentation-system/
13+
https://diataxis.fr/
14+
15+

docs/book.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[book]
2+
authors = ["Julien Nioche"]
3+
language = "en"
4+
src = "src"
5+
title = "SPRUCE"

docs/src/SUMMARY.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Summary
2+
3+
[Introduction](./intro.md)
4+
5+
# Tutorials 🚀
6+
7+
- [Quickstart with Docker 🐳](tutorial/with-docker.md)
8+
- [Quickstart with Apache Spark ⚡](tutorial/with-spark.md)
9+
- [Explore the results](tutorial/results.md)
10+
11+
# Explanations 📚
12+
13+
- [Methodology](./methodology.md)
14+
15+
# How-to 💡
16+
17+
- [Contribute to SPRUCE](./contributing.md)

docs/src/contributing.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Contributing to Spruce
2+
============================
3+
4+
Thank you for your intention to contribute to Spruce. As an open-source community, we highly appreciate contributions to our project.
5+
6+
To make the process smooth for the project *committers* (those who review and accept changes) and *contributors* (those who propose new changes via pull requests), there are a few rules to follow.
7+
8+
## Contribution Guidelines
9+
10+
We use GitHub Issues and Pull Requests for tracking contributions. We
11+
expect participants to adhere to the GitHub Community Guidelines (found
12+
at <https://help.github.com/articles/github-community-guidelines/> ) as well as our [Code of Conduct](CODE_OF_CONDUCT.md).
13+
14+
Please note that your contributions will be under the [ASF v2 license](LICENSE).
15+
16+
### Get Involved
17+
18+
The Spruce project is developed by volunteers and is always looking for new contributors to work on all parts of the project.
19+
Every contribution is welcome and needed to make it better. A contribution can be anything from a small documentation typo fix to a new component. We especially welcome contributions from first-time users.
20+
21+
#### GitHub Discussions
22+
23+
Feel free to use GitHub Discussions to ask any questions you might have when planning your first contribution.
24+
25+
### Making a Contribution
26+
27+
- Create a new issue on GitHub. Please describe the problem or improvement in the body of the issue. For larger issues, please open a new discussion and describe the problem.
28+
- Next, create a pull request in GitHub.
29+
30+
Contributors who have a history of successful participation are invited to join the project as a committer.

docs/src/images/logo.png

359 KB
Loading

docs/src/intro.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
![The SPRUCE Logo](images/logo.png)
3+
4+
*Spruce* helps estimate the environmental impact of your cloud usage. By leveraging open source models and data, it enriches
5+
usage reports generated by cloud providers and allows you to build reports and visualisations. Having the greenops and finops data in the same
6+
place makes it easier to expose your costs and impacts side by side.
7+
8+
*Spruce* uses [Apache Spark](https://spark.apache.org/) to read and write the usage reports (typically in Parquet format) in a scalable way and, thanks to its modular approach,
9+
splits the enrichment of the data into configurable stages.
10+
11+
A typical sequence of stages would be:
12+
- estimation of embodied emissions from the hardware
13+
- estimation of energy used
14+
- application of PUE and other overheads
15+
- application of carbon intensity factors
16+
17+
Please note that this is currently a prototype which handles only CUR reports from AWS. Not all AWS services are covered.
18+
19+
One of the benefits of using Apache Spark is that you can use [EMR on AWS](https://aws.amazon.com/emr/features/spark/) to enrich
20+
the CURs at scale without having to export or expose any of your data.
21+
22+
The code of the project can be found at https://github.com/DigitalPebble/spruce/.
23+
24+
Spruce is licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0

docs/src/methodology.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Methodology
2+
3+
Spruce uses third-party resources and models to estimate the environmental impact of cloud services. It enriches cost usage reports (CUR) with additional columns, allowing users to do GreenOps and build dashboards and reports.
4+
5+
Unlike the information provided by CSPs (Cloud Service Providers), Spruce gives total transparency on how the estimates are built.
6+
7+
The overall approach is as follows:
8+
1. Estimate the energy used per activity (e.g for X GB of data transferred, usage of an EC2 instance, storage etc...)
9+
2. Add overheads (e.g. PUE, WUE)
10+
3. Apply accurate carbon intensity factors - ideally for a specific location at a specific time
11+
4. Where possible, estimate the embodied carbon related to the activity
12+
13+
This is compliant with the [SCI specification](https://sci.greensoftware.foundation/) from the GreenSoftware Foundation.
14+
15+
## Enrichment modules
16+
17+
Spruce generates the estimates above by chaining **EnrichmentModules**, each of them relying on columns found in the usage reports or produced by preceding modules.
18+
19+
For instance, the [AverageCarbonIntensity.java](https://github.com/DigitalPebble/spruce/blob/main/src/main/java/com/digitalpebble/spruce/modules/electricitymaps/AverageCarbonIntensity.java) module applies average carbon intensity factors to energy estimates based on the region in order to generate _operational emissions_.
20+
21+
The list of columns generated by the modules can be found in the [SpruceColumn](https://github.com/DigitalPebble/spruce/blob/main/src/main/java/com/digitalpebble/spruce/SpruceColumn.java) class.
22+
23+
The enrichment modules are listed and configured in a configuration file. If no configuration is specified, the [default one](https://github.com/DigitalPebble/spruce/blob/main/src/main/resources/default-config.json) is used.
24+
25+
26+
### ccf.Storage
27+
28+
Provides an estimate of energy used for storage by applying a flat coefficient per Gb, following the approach used by the [Cloud Carbon Footprint](https://www.cloudcarbonfootprint.org/) project.
29+
See [methodology](https://www.cloudcarbonfootprint.org/docs/methodology#storage) for more details.
30+
31+
Populates the column `energy_usage_kwh`.
32+
33+
### ccf.Networking
34+
35+
Provides an estimate of energy used for networking in and out of data centres. Applies a flat coefficient per Gb, following the approach used by the [Cloud Carbon Footprint](https://www.cloudcarbonfootprint.org/) project.
36+
See [methodology](https://www.cloudcarbonfootprint.org/docs/methodology#storage) for more details.
37+
38+
Populates the column `energy_usage_kwh`.
39+
40+
### boavizta.BoaviztAPI
41+
42+
Provides an estimate of [final energy](https://www.eea.europa.eu/en/analysis/indicators/primary-and-final-energy-consumption) used for computation (EC2, OpenSearch, RDS) as well as the related embodied emissions using the [BoaviztAPI](https://doc.api.boavizta.org/).
43+
44+
Populates the column `energy_usage_kwh` and `embodied_emissions_co2eq_g`.
45+
46+
### boavizta.BoaviztAPIstatic
47+
48+
Similar to the previous module but does not get the information from an instance of the BoaviztAPI but from a static file generated from it. This makes it simpler to use Spruce.
49+
50+
### ccf.PUE
51+
52+
Applies a fixed ratio for [Power Usage_Effectiveness](https://en.wikipedia.org/wiki/Power_usage_effectiveness) to row for which energy usage has been estimated, following the approach used by the [Cloud Carbon Footprint](https://www.cloudcarbonfootprint.org/) project.
53+
See [CCF methodology](https://www.cloudcarbonfootprint.org/docs/methodology/#pue) for more details.
54+
55+
Populates the column `power_usage_effectiveness`.
56+
57+
### electricitymaps.AverageCarbonIntensity
58+
59+
Adds average carbon intensity factors generated from [ElectricityMaps](https://www.electricitymaps.com/)' 2024 datasets.
60+
The [life-cycle](https://portal.electricitymaps.com/developer-hub/api/getting-started#emission-factors) emission factors are used.
61+
62+
Populates the columns `carbon_intensity`.
63+
64+
### OperationalEmissions
65+
66+
Computes operational emissions based on the energy usage, average carbon intensity factors and `power_usage_effectiveness` estimated by the preceding modules.
67+
68+
Populates the columns `operational_emissions_co2eq_g`.
69+
70+
`operational_emissions_co2eq_g` is equal to `energy_usage_kwh` * `carbon_intensity` * 'power_usage_effectiveness'.

docs/src/tutorial/results.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
## Explore the output
2+
3+
Using [DuckDB](https://duckdb.org/) locally or [Athena](https://docs.aws.amazon.com/athena/latest/ug/what-is.html) on AWS:
4+
5+
```sql
6+
create table enriched_curs as select * from 'output/**/*.parquet';
7+
8+
select line_item_product_code, product_servicecode,
9+
round(sum(operational_emissions_co2eq_g)/1000,2) as co2_usage_kg,
10+
round(sum(embodied_emissions_co2eq_g)/1000, 2) as co2_embodied_kg,
11+
round(sum(energy_usage_kwh),2) as energy_usage_kwh
12+
from enriched_curs where operational_emissions_co2eq_g > 0.01
13+
group by line_item_product_code, product_servicecode
14+
order by co2_usage_kg desc, co2_embodied_kg desc, energy_usage_kwh desc, product_servicecode;
15+
```
16+
17+
This should give an output similar to
18+
19+
| line_item_product_code | product_servicecode | line_item_operation | co2_usage_kg | energy_usage_kwh | co2_embodied_kg |
20+
|------------------------|---------------------|--------------------------------|-------------:|-----------------:|----------------:|
21+
| AmazonEC2 | AmazonEC2 | RunInstances | 538.3 | 1220.14 | 303.41 |
22+
| AmazonECS | AmazonECS | FargateTask | 181.32 | 399.05 | NULL |
23+
| AmazonS3 | AmazonS3 | OneZoneIAStorage | 102.3 | 225.15 | NULL |
24+
| AmazonS3 | AmazonS3 | GlacierInstantRetrievalStorage | 75.89 | 167.03 | NULL |
25+
| AmazonEC2 | AmazonEC2 | CreateVolume-Gp3 | 41.63 | 91.62 | NULL |
26+
| AmazonS3 | AmazonS3 | StandardStorage | 28.51 | 62.81 | NULL |
27+
| AmazonDocDB | AmazonDocDB | CreateCluster | 19.79 | 43.56 | NULL |
28+
| AmazonECS | AmazonECS | ECSTask-EC2 | 9.26 | 20.37 | NULL |
29+
| AmazonS3 | AmazonS3 | IntelligentTieringAIAStorage | 2.33 | 5.13 | NULL |
30+
| AmazonEC2 | AmazonEC2 | CreateSnapshot | 2.31 | 5.82 | NULL |
31+
| AmazonEC2 | AmazonEC2 | RunInstances:SV001 | 1.79 | 3.94 | 0.78 |
32+
| AmazonS3 | AmazonS3 | StandardIAStorage | 1.19 | 2.61 | NULL |
33+
| AmazonS3 | AWSDataTransfer | GetObjectForRepl | 1.17 | 2.58 | NULL |
34+
| AmazonS3 | AWSDataTransfer | UploadPartForRepl | 1.01 | 2.22 | NULL |
35+
| AmazonS3 | AmazonS3 | OneZoneIASizeOverhead | 0.89 | 1.96 | NULL |
36+
| AmazonEC2 | AmazonEC2 | CreateVolume-Gp2 | 0.84 | 1.84 | NULL |
37+
| AmazonEC2 | AWSDataTransfer | RunInstances | 0.18 | 0.39 | NULL |
38+
| AmazonS3 | AWSDataTransfer | PutObjectForRepl | 0.16 | 0.36 | NULL |
39+
| AmazonS3 | AmazonS3 | DeleteObject | 0.16 | 0.35 | NULL |
40+
| AWSBackup | AWSBackup | Storage | 0.1 | 0.49 | NULL |
41+
| AmazonMQ | AmazonMQ | CreateBroker:0001 | 0.02 | 0.04 | NULL |
42+
| AmazonECR | AWSDataTransfer | downloadLayer | 0.01 | 0.01 | NULL |
43+
| AmazonS3 | AWSDataTransfer | PutObject | 0.0 | 0.0 | NULL |
44+
45+
To measure the proportion of the costs for which emissions where calculated
46+
47+
```sql
48+
select
49+
round(covered * 100 / "total costs", 2) as percentage_costs_covered
50+
from (
51+
select
52+
sum(line_item_unblended_cost) as "total costs",
53+
sum(line_item_unblended_cost) filter (where operational_emissions_co2eq_g is not null) as covered
54+
from
55+
enriched_curs
56+
where
57+
line_item_line_item_type like '%Usage'
58+
);
59+
```

0 commit comments

Comments
 (0)