Skip to content

Commit 6678451

Browse files
Merge pull request #121 from Green-Software-Foundation/update-docs
Update the documentation's reference links and add samples
2 parents 9449896 + 3fc02cc commit 6678451

19 files changed

+184
-115
lines changed

docs/developers/how-to-build-plugins.md

+33-5
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ b) instruct the second plugin to accept `cpu-energy` instead of the default `cpu
121121
The `mapping` config is an object with key-value pairs, where the `key` is the 'original' parameter name that the plugin uses, and the `value` is the 'new' name that you want to use instead.
122122
The `mapping` block is an optional and allows mapping the input and output parameters of the plugin. The structure of the `mapping` block is:
123123

124+
#### Mapping config and output
125+
124126
```yaml
125127
name: sci
126128
description: successful path
@@ -132,9 +134,10 @@ initialize:
132134
method: Sci
133135
path: 'builtin'
134136
config:
135-
functional-unit: requests
137+
functional-unit: if-requests
136138
mapping:
137-
sci: if-sci
139+
sci: if-sci # mapping output parameter
140+
requests: if-requests # mapping config parameter
138141
tree:
139142
children:
140143
child:
@@ -148,11 +151,36 @@ tree:
148151
carbon-operational: 5
149152
carbon-embodied: 0.02
150153
carbon: 5.02
151-
requests: 100
154+
if-requests: 100
152155
```
153156

154157
In the `outputs`, the `sci` value returned by the `Sci` plugin will be named `if-sci`.
155158

159+
#### Mapping input
160+
161+
```yaml
162+
name: embodied-carbon demo
163+
description:
164+
tags:
165+
initialize:
166+
plugins:
167+
embodied-carbon:
168+
method: SciEmbodied
169+
path: builtin
170+
mapping:
171+
hdd: 'hdd-mapped' # mapping input parameter
172+
tree:
173+
children:
174+
child:
175+
pipeline:
176+
compute:
177+
- embodied-carbon
178+
inputs:
179+
- timestamp: 2023-08-06T00:00
180+
duration: 3600
181+
hdd-mapped: 2
182+
```
183+
156184
### Plugin example
157185

158186
Here’s a minimal example of a plugin that sums inputs based on the configuration:
@@ -274,7 +302,7 @@ Then, in your manifest file, provide the path in the plugin instantiation. You a
274302
```yaml
275303
name: plugin-demo
276304
description: loads plugin
277-
tags: null
305+
tags:
278306
initialize:
279307
plugins:
280308
new-plugin:
@@ -309,7 +337,7 @@ You should also create unit tests for your plugin to demonstrate correct executi
309337

310338
You can read our more advanced guide on [how to refine your plugins](./how-to-refine-plugins.md).
311339

312-
## Appendix: Walk-through of the Sci plugin
340+
## Appendix: Walk-through of the Sum plugin
313341

314342
To demonstrate how to build a plugin that conforms to the `PluginFactory`, let's examine the `Sum` plugin.
315343

docs/developers/how-to-create-exhaust-script.md

+13-9
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,28 @@ sidebar-position: 6
44

55
# How to create an exhaust script
66

7-
The `If` framework outputs data in `yaml` format. Any other output formats require a separate script that takes the yaml output data and processes it. We provide [`if-csv`](../users/how-to-export-csv-file-with-if-csv.md) for outputting data in `csv` format bundled with IF. For any other format, you need to write an exhaust script.
7+
The `IF` framework outputs data in `yaml` format. Any other output formats require a separate script that takes the yaml output data and processes it. We provide [`if-csv`](../users/how-to-export-csv-file-with-if-csv.md) for outputting data in `csv` format bundled with IF. For any other format, you need to write an exhaust script.
88
This guide will help you create your own exhaust script.
99

1010
In this example, we'll create a script that executes the manifest and outputs the data in `json` format.
1111

1212
```ts
1313
const IfJson = async () => {
14-
const { manifest, output } = await parseIfCsvArgs();
14+
const { manifest, output, params } = await parseIfCsvArgs();
1515

1616
if (manifest) {
17-
const { rawManifest } = await load(manifest);
18-
const { children } = rawManifest.tree;
19-
20-
if (!(children?.child || children?.['child-0']).outputs) {
21-
throw new ManifestValidationError(FAILURE_MESSAGE_OUTPUTS);
17+
const manifestData = await getManifestData(manifest!);
18+
const options: CsvOptions = {
19+
tree: manifestData.tree,
20+
context: manifestData,
21+
outputPath: output,
22+
params,
23+
};
24+
const result = await generateCsv(options);
25+
26+
if (!output && result) {
27+
console.log(result);
2228
}
23-
24-
// Add logic to export the executed manifest to `json` format.
2529
}
2630

2731
process.exit(0);

docs/developers/how-to-refine-plugins.md

+38-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ sidebar-position: 2
44

55
# How to make plugins production ready
66

7-
Our [How to build plugins](./how-to-build-plugins.md) guide covered the basics for how to construct an Impact Framework plugin. This guide will help you to refine your plugin to make it production-ready. These are best practice guidelines - if you intend to contribute your plugin to one of our repositories, following these guidelines will help your PR to get merged. Even if you are not aiming to have a plugin merged into one of our repositories, consistency with our norms is useful for debugging and maintaining and for making your plugin as useful as possible for other Impact Framework developers.
7+
Our [How to build plugins](./how-to-build-plugins.md) guide covered the basics for how to construct an Impact Framework plugin. This guide will help you to refine your plugin to make it production-ready. These are best practice guidelines - if you intend to contribute to one of our repositories, following these guidelines will help your PR to get merged. Consistency with our norms is useful for debugging and maintaining and for making your plugin as useful as possible for other Impact Framework developers.
88

99
## 1. Naming conventions
1010

@@ -79,6 +79,8 @@ throw new MissingInputDataError("my-plugin is missing my-parameter from inputs[0
7979

8080
### Validation
8181

82+
#### Input Validation
83+
8284
We recommend using `inputValidation` property from `PluginFactory` for validation to ensure the integrity of input data. Validate input parameters against expected types, ranges, or constraints to prevent runtime errors and ensure data consistency.
8385

8486
You need to use `zod` schema or `InputValidatorFunction`. Here's an example from our codebase:
@@ -114,6 +116,41 @@ inputValidation: z.object({
114116
});
115117
```
116118

119+
#### Config Validation
120+
121+
To validate the `config`, you need to use `configValidation` property from `PluginFactory`. Validate config parameters against expected types, ranges, or constraints to prevent runtime errors and ensure data consistency.
122+
123+
You need to use `zod` schema or `ConfigValidatorFunction`:
124+
125+
- When using function with `ConfigValidatorFunction` type.
126+
127+
```ts
128+
configValidation: (config: ConfigParams) => {
129+
const configSchema = z.object({
130+
coefficient: z.preprocess(
131+
(value) => validateArithmeticExpression('coefficient', value, 'number'),
132+
z.number()
133+
),
134+
'input-parameter': z.string().min(1),
135+
'output-parameter': z.string().min(1),
136+
});
137+
138+
return validate<z.infer<typeof configSchema>>(
139+
configSchema as ZodType<any>,
140+
config
141+
);
142+
};
143+
```
144+
145+
- When using `zod` schema
146+
147+
```ts
148+
configValidation: z.object({
149+
'input-parameters': z.array(z.string()),
150+
'output-parameter': z.string().min(1),
151+
}),
152+
```
153+
117154
### Code Modularity
118155

119156
Break down complex functionality into smaller, manageable methods with well-defined responsibilities.

docs/developers/how-to-write-unit-tests.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ it('throws an exception on missing functional unit data.', async () => {
144144
expect.assertions(1);
145145

146146
try {
147-
await sciModel.execute(inputs);
147+
await sciPlugin.execute(inputs);
148148
} catch (error) {
149149
expect(error).toBeInstanceOf(InputValidationError);
150150
}

docs/developers/index.md

+5-7
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ sidebar_position: 4
44

55
# Developers
66

7-
This section contains information for Impact Framework developers. You are a developer if you want to *change or update* the Impact Framework by adding new features, fixing bugs or building new plugins.
7+
This section contains information for Impact Framework developers. You are a developer if you want to _change or update_ the Impact Framework by adding new features, fixing bugs or building new plugins.
88

99
The developer documentation includes:
1010

11-
* [How to build plugins](./how-to-build-plugins.md)
12-
* [How to make plugins production-ready](./how-to-refine-plugins.md)
13-
* [How to write unit tests](./how-to-write-unit-tests.md)
14-
* [How to visualize results](./how-to-visualize-results.md)
15-
* [How to create exhaust scripts](./how-to-create-exhaust-script.md)
16-
11+
- [How to build plugins](./how-to-build-plugins.md)
12+
- [How to make plugins production-ready](./how-to-refine-plugins.md)
13+
- [How to write unit tests](./how-to-write-unit-tests.md)
14+
- [How to create exhaust scripts](./how-to-create-exhaust-script.md)
1715

1816
If you are looking for guidance for how to use IF to measure the environmental impact of your apps, you should go to our [`user` documentation](../users/) instead.

docs/intro.md

+6-10
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,21 @@ IF allows you to calculate the environmental impacts, such as carbon, of your so
1414

1515
The project is entirely open source and composability is a core design principle - we want you to be able to create your own plugins and plug them in to our framework, or pick from a broad universe of open source plugins created by others.
1616

17-
18-
## Motivation
17+
## Motivation
1918

2019
If you can't measure, you can't improve. Software has many negative environmental **impacts** which we need to optimize, carbon, water, and energy, to name just a few.
2120

22-
Unfortunately, measuring software impact metrics like carbon, water, and energy is complex and nuanced.
21+
Unfortunately, measuring software impact metrics like carbon, water, and energy is complex and nuanced.
2322

24-
Modern applications are composed of many smaller pieces of software (components) running on different environments, for example, private cloud, public cloud, bare-metal, virtualized, containerized, mobile, laptops, desktops, embedded, and IoT. Many components that make up a typical software application are run on something other than resources you own or control, which makes including the impact of managed services in your measurement especially hard.
23+
Modern applications are composed of many smaller pieces of software (components) running on different environments, for example, private cloud, public cloud, bare-metal, virtualized, containerized, mobile, laptops, desktops, embedded, and IoT. Many components that make up a typical software application are run on something other than resources you own or control, which makes including the impact of managed services in your measurement especially hard.
2524

2625
The impacts of software components also vary over time, so as well as understanding **which** components contribute most to the overall impacts, there is also a question of **when** they contribute the most.
2726

2827
Only through a granular analysis of the impacts of your software system can investments in reducing its impact be prioritized and verified. Measurement is the first and most crucial step in greening a software system, and the first step in that process with the Impact Framework is to create a tree.
2928

30-
3129
## Background
3230

33-
This project has evolved over the two years of the GSF's existence.
31+
This project has evolved over the two years of the GSF's existence.
3432

3533
During the development of the [SCI](https://github.com/Green-Software-Foundation/sci/blob/dev/SPEC.md), we acknowledged that the biggest blocker to adoption was data regarding the emissions of software components on different platforms and runtimes.
3634

@@ -42,8 +40,7 @@ The project evolved into the [sci-guide](https://sci-guide.greensoftware.foundat
4240

4341
Finally, we had enough information, and [SCI case studies](https://sci-guide.greensoftware.foundation/CaseStudies) started to be written. This was a milestone moment.
4442

45-
But now we are in the next evolution, to have software measurement be a mainstream activity. For this to be an industry with thousands of professionals working to decarbonize software, for businesses to grow and thrive in a commercial software measurement ecosystem, we need to formalize software measurement into a discipline with standards and tooling. The SCI Specification is the standard, and the [Impact Framework](./06-specification/impact-framework.md) is the tooling.
46-
43+
But now we are in the next evolution, to have software measurement be a mainstream activity. For this to be an industry with thousands of professionals working to decarbonize software, for businesses to grow and thrive in a commercial software measurement ecosystem, we need to formalize software measurement into a discipline with standards and tooling. The SCI Specification is the standard, and the Impact Framework is the tooling.
4744

4845
## Project Structure
4946

@@ -55,10 +52,9 @@ There are also a wide range of community-owned plugins that we make discoverable
5552

5653
Finally, the **source code for this documentation** website is available at the [`if-docs` Github repository](https://github.com/Green-Software-Foundation/if-docs).
5754

58-
5955
## Navigating these docs
6056

61-
The lefthand sidebar contains links to all the information you need to understand Impact Framework.
57+
The lefthand sidebar contains links to all the information you need to understand Impact Framework.
6258

6359
You can explore the key ideas underpinning Impact Framework in the [Major Concepts section](./major-concepts/index.md).
6460

docs/major-concepts/exhaust-script.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ You will get the executed manifest in the `output-sum.yaml` file.
5353

5454
## if-csv
5555

56-
The [`if-csv`](../users/how-to-export-csv-file-with-if-csv.md) script allows users to pass in `yaml` and `yml` files created using `if-run` and save the output in `csv` format. Yopu have to define the parameters you want to export from the yaml file, e.g. `energy` or `carbon`.
56+
The [`if-csv`](../users/how-to-export-csv-file-with-if-csv.md) script allows users to pass in `yaml` and `yml` files created using `if-run` and save the output in `csv` format. You have to define the parameters you want to export from the yaml file, e.g. `energy` or `carbon`.
5757

5858
For the above example, you can get the following result:
5959

docs/major-concepts/if.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ The available options and their shortcuts are:
1717
- `--help` or `-h`: prints out help instruction
1818
- `--debug`: enables IF execution logs
1919
- `--append`: allows you to rerun an already-computed manifest and append new values to the existing data.
20+
- `--observe`: runs only `observe` phases of the manifest execution
21+
- `--regroup`: runs only `regroup` phases of the manifest execution
22+
- `--compute`: runs only `compute` phases of the manifest execution
2023

2124
The only required command is `--manifest`. Without a valid path to a manifest file, `if-run` has nothing to execute.
2225

@@ -42,7 +45,7 @@ For more information on the `if-run` commands see the [CLI reference documentati
4245

4346
## Phased execution
4447

45-
To enable greener and more flexible use of IF, we separate the manifest execution into distinct phases: `observe`, `regroup` and `compute`. This is invisible to you when you run `if-run` but behind the scenes all three of these phases are being run. However, you can instruct IF to run these phases individually, to avoid recomputing parts of the manifest unnecessarily. To do this, you simply pass `--observe`, `--regroup`, and `--compute` flags to IF in the combination you need. For example, to run *only* the observe phase (to generate input data):
48+
To enable greener and more flexible use of IF, we separate the manifest execution into distinct phases: `observe`, `regroup` and `compute`. This is invisible to you when you run `if-run` but behind the scenes all three of these phases are being run. However, you can instruct IF to run these phases individually, to avoid recomputing parts of the manifest unnecessarily. To do this, you simply pass `--observe`, `--regroup`, and `--compute` flags to IF in the combination you need. For example, to run _only_ the observe phase (to generate input data):
4649

4750
```
4851
if-run -m <manifest> --observe

docs/major-concepts/manifest-file.md

+12-10
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Everything above the `tree` is collectively referred to as the `context`. The `t
5555

5656
#### Metadata
5757

58-
The global metadata includes the `name`, `description`, and `tags` that can be used to describe the nature of the manifest file. For example, you might name the file `Carbon Jan 2024` or similar. A short description might briefly outline the scope of the manifest file, e.g. `company x's carbon emissions due to web serves from Jab 24 - July 24`. Tags can be used to group manifest files (we do not explicitly use this field for anything currently).
58+
The global metadata includes the `name`, `description`, and `tags` that can be used to describe the nature of the manifest file. For example, you might name the file `Carbon Jan 2024` or similar. A short description might briefly outline the scope of the manifest file, e.g. `company x's carbon emissions due to web serves from Jab 24 - July 24`. Tags is an object containing the string properties `kind`, `complexity` and `category`. It can be used to group manifest files (we do not explicitly use this field for anything currently).
5959

6060
#### Initialize
6161

@@ -79,11 +79,11 @@ Impact Framework uses the `initialize` section to instantiate each plugin. A plu
7979

8080
There is also the option to provide a mapping to the plugin in the initialize block. Its purpose is to rename the arguments expected or returned from the plugin as part of the plugin's execution, avoiding the need to use additional plugins to rename parameters.
8181

82-
For example, your plugin might expect cpu/energy and your input data has the parameter cpu-energy returned from another plugin. Instead of using an additional plugin to rename the parameter and add a new one, you can use mapping to:
82+
For example, your plugin might expect `cpu/energy` and your input data has the parameter `cpu-energy` returned from another plugin. Instead of using an additional plugin to rename the parameter and add a new one, you can use mapping to:
8383

84-
a) rename the output from the first plugin so that cpu/energy is returned instead of the default cpu-energy
84+
a) rename the output from the first plugin so that `cpu/energy` is returned instead of the default `cpu-energy`
8585

86-
b) instruct the second plugin to accept cpu-energy instead of the default cpu/energy
86+
b) instruct the second plugin to accept `cpu-energy` instead of the default `cpu/energy`
8787

8888
e.g.
8989

@@ -102,6 +102,8 @@ initialize:
102102

103103
In the outputs, the `sci` value returned by the Sci plugin will be named if-sci.
104104

105+
[Read more on mapping](../developers/how-to-build-plugins.md#mapping)
106+
105107
You can also add information to the plugin's initialize section about parameter metadata if you wish to add or override the metadata hardcoded into the plugin. This is what will be reported by the `explainer` feature if you enable it. E.g.
106108

107109
```yaml
@@ -161,7 +163,7 @@ This section is autogenerated at runtime. It is a list of all the parameter meta
161163

162164
```yaml
163165
explain:
164-
sci:
166+
sci-plugin:
165167
inputs:
166168
carbon:
167169
unit: gCO2eq
@@ -225,7 +227,7 @@ Each component has some configuration, some input data, and a plugin pipeline.
225227
- `defaults`: fallback values that IF defaults to if they are not present in an input observation.
226228
- `inputs`: an array of `observation` data, with each `observation` containing usage data for a given timestep.
227229

228-
If a component _does not_ include its own `pipeline` or `default` values, they are inherited from the closest parent.
230+
If a component _does not_ include its own `pipeline` or `defaults` values, they are inherited from the closest parent.
229231

230232
Here's an example of a moderately complex tree:
231233

@@ -240,7 +242,7 @@ tree:
240242
regroup:
241243
compute:
242244
- sum
243-
defaults: null
245+
defaults:
244246
inputs:
245247
- timestamp: 2023-07-06T00:00
246248
duration: 10
@@ -260,7 +262,7 @@ tree:
260262
regroup:
261263
compute:
262264
- sum
263-
defaults: null
265+
defaults:
264266
inputs:
265267
- timestamp: 2023-07-06T00:00
266268
duration: 10
@@ -379,11 +381,11 @@ tree:
379381
children:
380382
my-app:
381383
pipeline:
382-
observe: null
384+
observe:
383385
regroup:
384386
- cloud/instance-type
385387
- cloud/region
386-
compute: null
388+
compute:
387389
children:
388390
A1:
389391
children:

0 commit comments

Comments
 (0)