-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Paz Barda <[email protected]>
- Loading branch information
1 parent
4a2998a
commit 8c980e9
Showing
6 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import {Subtract} from '../../../../lib'; | ||
|
||
import {ERRORS} from '../../../../util/errors'; | ||
|
||
const {InputValidationError} = ERRORS; | ||
|
||
describe('lib/subtract: ', () => { | ||
describe('Subtract: ', () => { | ||
const globalConfig = { | ||
'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], | ||
'output-parameter': 'energy/diff', | ||
}; | ||
const subtract = Subtract(globalConfig); | ||
|
||
describe('init: ', () => { | ||
it('successfully initalized.', () => { | ||
expect(subtract).toHaveProperty('metadata'); | ||
expect(subtract).toHaveProperty('execute'); | ||
}); | ||
}); | ||
|
||
describe('execute(): ', () => { | ||
it('successfully applies Subtract strategy to given input.', async () => { | ||
expect.assertions(1); | ||
|
||
const expectedResult = [ | ||
{ | ||
duration: 3600, | ||
'cpu/energy': 4, | ||
'network/energy': 2, | ||
'memory/energy': 1, | ||
'energy/diff': 1, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
}, | ||
]; | ||
|
||
const result = await subtract.execute([ | ||
{ | ||
duration: 3600, | ||
'cpu/energy': 4, | ||
'network/energy': 2, | ||
'memory/energy': 1, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
}, | ||
]); | ||
|
||
expect(result).toStrictEqual(expectedResult); | ||
}); | ||
|
||
it('throws an error on missing params in input.', async () => { | ||
const expectedMessage = | ||
'Subtract: cpu/energy is missing from the input array.'; | ||
|
||
expect.assertions(1); | ||
|
||
try { | ||
await subtract.execute([ | ||
{ | ||
duration: 3600, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
}, | ||
]); | ||
} catch (error) { | ||
expect(error).toStrictEqual( | ||
new InputValidationError(expectedMessage) | ||
); | ||
} | ||
}); | ||
|
||
it('returns a result with input params not related to energy.', async () => { | ||
expect.assertions(1); | ||
const newConfig = { | ||
'input-parameters': ['carbon', 'other-carbon'], | ||
'output-parameter': 'carbon-diff', | ||
}; | ||
const subtract = Subtract(newConfig); | ||
|
||
const data = [ | ||
{ | ||
duration: 3600, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
carbon: 3, | ||
'other-carbon': 2, | ||
}, | ||
]; | ||
const response = await subtract.execute(data); | ||
|
||
const expectedResult = [ | ||
{ | ||
duration: 3600, | ||
carbon: 3, | ||
'other-carbon': 2, | ||
'carbon-diff': 1, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
}, | ||
]; | ||
|
||
expect(response).toEqual(expectedResult); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# Sum | ||
|
||
`subtract` is a generic plugin for doing arithmetic subtractions of two or more values in an `input` array. | ||
|
||
You provide the names of the values you want to subtract, and a name to use to add the subtraction to the output array. | ||
|
||
For example, you could subtract `cpu/energy` and `network/energy` and name the result `offset/energy`. `offset/energy` would then be added to every observation in your input array as the diff of `cpu/energy` and `network/energy`. | ||
|
||
## Parameters | ||
|
||
### Plugin config | ||
|
||
Two parameters are required in global config: `input-parameters` and `output-parameter`. | ||
|
||
`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array | ||
`output-parameter`: a string defining the name to use to add the result of summing the input parameters to the output array. | ||
|
||
### Inputs | ||
|
||
All of `input-parameters` must be available in the input array. | ||
|
||
## Returns | ||
|
||
- `output-parameter`: the subtraction of all `input-parameters` with the parameter name defined by `output-parameter` in global config. | ||
|
||
## Calculation | ||
|
||
```pseudocode | ||
output = input0 - input1 - input2 ... - inputN | ||
``` | ||
|
||
## Implementation | ||
|
||
To run the plugin, you must first create an instance of `Subtract`. Then, you can call `execute()`. | ||
|
||
```typescript | ||
import {Subtract} from '@grnsft/if-plugins'; | ||
|
||
const config = { | ||
inputParameters: ['cpu/energy', 'network/energy'], | ||
outputParameter: 'offset/energy', | ||
}; | ||
|
||
const sum = Sum(config); | ||
const result = await sum.execute([ | ||
{ | ||
duration: 3600, | ||
timestamp: '2021-01-01T00:00:00Z', | ||
'cpu/energy': 0.001, | ||
'memory/energy': 0.0005, | ||
}, | ||
]); | ||
``` | ||
|
||
## Example manifest | ||
|
||
IF users will typically call the plugin as part of a pipeline defined in a manifest file. In this case, instantiating the plugin is handled by and does not have to be done explicitly by the user. The following is an example manifest that calls `sum`: | ||
|
||
```yaml | ||
name: subtract demo | ||
description: | ||
tags: | ||
initialize: | ||
outputs: | ||
- yaml | ||
plugins: | ||
subtract: | ||
method: Subtract | ||
path: '@grnsft/if-plugins' | ||
global-config: | ||
input-parameters: ['cpu/energy', 'network/energy'] | ||
output-parameter: 'offset/' | ||
tree: | ||
children: | ||
child: | ||
pipeline: | ||
- subtract | ||
config: | ||
sum: | ||
inputs: | ||
- timestamp: 2023-08-06T00:00 | ||
duration: 3600 | ||
cpu/energy: 0.003 | ||
network/energy: 0.001 | ||
``` | ||
You can run this example by saving it as `./examples/manifests/test/subrtact.yml` and executing the following command from the project root: | ||
|
||
```sh | ||
npm i -g @grnsft/if | ||
npm i -g @grnsft/if-plugins | ||
ie --manifest ./examples/manifests/test/subtract.yml --output ./examples/outputs/subtract.yml | ||
``` | ||
|
||
The results will be saved to a new `yaml` file in `./examples/outputs`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import {z} from 'zod'; | ||
|
||
import {ERRORS} from '../../util/errors'; | ||
import {buildErrorMessage} from '../../util/helpers'; | ||
import {validate} from '../../util/validations'; | ||
|
||
import {PluginInterface} from '../../interfaces'; | ||
import {PluginParams} from '../../types/common'; | ||
import {SubtractConfig} from './types'; | ||
|
||
const {InputValidationError} = ERRORS; | ||
|
||
export const Subtract = (globalConfig: SubtractConfig): PluginInterface => { | ||
const errorBuilder = buildErrorMessage(Subtract.name); | ||
const metadata = { | ||
kind: 'execute', | ||
}; | ||
|
||
/** | ||
* Checks global config value are valid. | ||
*/ | ||
const validateGlobalConfig = () => { | ||
const globalConfigSchema = z.object({ | ||
'input-parameters': z.array(z.string()), | ||
'output-parameter': z.string().min(1), | ||
}); | ||
|
||
return validate<z.infer<typeof globalConfigSchema>>( | ||
globalConfigSchema, | ||
globalConfig | ||
); | ||
}; | ||
|
||
/** | ||
* Checks for required fields in input. | ||
*/ | ||
const validateSingleInput = ( | ||
input: PluginParams, | ||
inputParameters: string[] | ||
) => { | ||
inputParameters.forEach(metricToSubtract => { | ||
if (!input[metricToSubtract]) { | ||
throw new InputValidationError( | ||
errorBuilder({ | ||
message: `${metricToSubtract} is missing from the input array`, | ||
}) | ||
); | ||
} | ||
}); | ||
|
||
return input; | ||
}; | ||
|
||
/** | ||
* Calculate the diff of each . | ||
*/ | ||
const execute = async (inputs: PluginParams[]): Promise<PluginParams[]> => { | ||
const safeGlobalConfig = validateGlobalConfig(); | ||
const inputParameters = safeGlobalConfig['input-parameters']; | ||
const outputParameter = safeGlobalConfig['output-parameter']; | ||
|
||
return inputs.map(input => { | ||
const safeInput = validateSingleInput(input, inputParameters); | ||
|
||
return { | ||
...safeInput, | ||
[outputParameter]: calculateDiff(safeInput, inputParameters), | ||
}; | ||
}); | ||
}; | ||
|
||
/** | ||
* Calculates the sum of the energy components. | ||
*/ | ||
const calculateDiff = (input: PluginParams, inputParameters: string[]) => { | ||
const [firstItem, ...restItems] = inputParameters; | ||
return restItems.reduce( | ||
(accumulator, metricToSubtract) => accumulator - input[metricToSubtract], | ||
input[firstItem] // Starting accumulator with the value of the first item | ||
); | ||
}; | ||
|
||
return { | ||
metadata, | ||
execute, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export type SubtractConfig = { | ||
'input-parameters': string[]; | ||
'output-parameter': string; | ||
}; |