Skip to content

Commit 1324b75

Browse files
authored
Merge pull request #188 from DataCloud-project/carbontracker
Full integration of Carbontracker * Display detailed carbon emissions and energy consumption related to dry-runs
2 parents 435ae06 + b0f4012 commit 1324b75

File tree

7 files changed

+173
-15
lines changed

7 files changed

+173
-15
lines changed

frontend/package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "frontend",
3-
"version": "0.4.0",
3+
"version": "0.4.1",
44
"private": true,
55
"scripts": {
66
"dev": "vite dev",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { gql } from 'graphql-request';
2+
3+
const getCarbontrackerDataQuery = gql`
4+
query fetchCarbontrackerData($input: CarbonTrackerInput!) {
5+
fetchCarbontrackerData(input: $input) {
6+
duration
7+
cpuModel
8+
cpuPowerData
9+
averagePowerUsage
10+
energyUsage
11+
location
12+
carbonIntensity
13+
energy
14+
co2eq
15+
}
16+
}
17+
`;
18+
19+
export default getCarbontrackerDataQuery;

frontend/src/queries/get_dry_run_metrics.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const getDryRunMetricsQuery = gql`
1212
phase
1313
type
1414
... on DryRunNodePod {
15+
id
1516
displayName
1617
startedAt
1718
finishedAt

frontend/src/queries/get_dry_run_phase_results.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const getDryRunPhaseResultsQuery = gql`
88
phase
99
type
1010
... on DryRunNodePod {
11+
id
1112
displayName
1213
startedAt
1314
finishedAt

frontend/src/routes/projects/dryruns/[dry_run]/[resource]/+page.svelte

Lines changed: 145 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import getProjectQuery from '$queries/get_project';
88
import getDryRunPhaseResultsQuery from '$queries/get_dry_run_phase_results';
99
import getDryRunQuery from '$queries/get_selected_project';
10+
import getCarbontrackerDataQuery from '$queries/get_carbontracker_metrics';
1011
import { requestGraphQLClient } from '$lib/graphqlUtils';
1112
import { goto } from '$app/navigation';
1213
import Plot from './plot.svelte';
@@ -23,6 +24,16 @@
2324
// import { displayAlert } from '$utils/alerts-utils';
2425
import type { DryRunMetrics, DryRun, MetricsWithTimeStamps } from '$typesdefinitions';
2526
27+
// Extended type to include carbontracker data
28+
interface ExtendedDryRunMetrics extends DryRunMetrics {
29+
carbontracker?: {
30+
fetchCarbontrackerData?: {
31+
co2eq: number;
32+
energy: number;
33+
};
34+
};
35+
}
36+
2637
export let data;
2738
2839
let loadingFinished = false;
@@ -49,7 +60,8 @@
4960
let allStepNames: string[] = [];
5061
5162
$: selectedStep = 'Total';
52-
$: reactiveStepsList = $stepsList;
63+
let reactiveStepsList: ExtendedDryRunMetrics[];
64+
$: reactiveStepsList = ($stepsList as ExtendedDryRunMetrics[]) || [];
5365
5466
function gotoOverview(): void {
5567
selectedStep = 'Total';
@@ -72,6 +84,8 @@
7284
let networkTotalReceived = 'N/A';
7385
let networkTotalTransmitted = 'N/A';
7486
let pipelineDuration = 'N/A';
87+
let totalCO2 = 'N/A';
88+
let totalEnergy = 'N/A';
7589
7690
function formatDuration(seconds: number): string {
7791
const hours = Math.floor(seconds / 3600);
@@ -107,9 +121,35 @@
107121
pipelineDuration = formatDuration(totalDuration);
108122
}
109123
124+
function computeTotalCarbonMetrics(): void {
125+
let co2Sum = 0;
126+
let energySum = 0;
127+
128+
if (reactiveStepsList) {
129+
reactiveStepsList.forEach((step) => {
130+
if (step.carbontracker?.fetchCarbontrackerData) {
131+
if (step.carbontracker.fetchCarbontrackerData.co2eq) {
132+
co2Sum += step.carbontracker.fetchCarbontrackerData.co2eq;
133+
}
134+
if (step.carbontracker.fetchCarbontrackerData.energy) {
135+
energySum += step.carbontracker.fetchCarbontrackerData.energy;
136+
}
137+
}
138+
});
139+
}
140+
141+
totalCO2 = co2Sum > 0 ? co2Sum.toFixed(3) : 'N/A';
142+
totalEnergy = energySum > 0 ? energySum.toFixed(6) : 'N/A';
143+
}
144+
145+
// Reactive statement to compute carbon metrics when reactiveStepsList changes
146+
$: if (reactiveStepsList && reactiveStepsList.length > 0) {
147+
computeTotalCarbonMetrics();
148+
}
149+
110150
let dryRunPhaseMessage: string | null;
111151
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, consistent-return
112-
const getMetricsResponse = async () => {
152+
const getMetricsResponse = async (): Promise<DryRunMetrics[]> => {
113153
const dryrunVariables = {
114154
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
115155
dryRunId: data.resource
@@ -124,9 +164,50 @@
124164
const body = `${(error as Error).message}`;
125165
// await displayAlert(title, body, 10_000);
126166
console.log(title, body);
167+
return [];
127168
}
128169
};
129170
171+
async function getCarbontrackerDataResponse(input: any): Promise<
172+
| {
173+
fetchCarbontrackerData?: {
174+
co2eq: number;
175+
energy: number;
176+
};
177+
}
178+
| undefined
179+
> {
180+
const inputData = {
181+
input: {
182+
data: {
183+
dryRun: {
184+
node: {
185+
metrics: {
186+
cpuUsageSecondsTotal: input
187+
}
188+
}
189+
}
190+
}
191+
}
192+
};
193+
console.log('inputData:', inputData);
194+
try {
195+
const response = await requestGraphQLClient(getCarbontrackerDataQuery, inputData);
196+
return response as {
197+
fetchCarbontrackerData?: {
198+
co2eq: number;
199+
energy: number;
200+
};
201+
};
202+
} catch (error) {
203+
const title = 'Internal error!';
204+
const body = `${(error as Error).message}`;
205+
// await displayAlert(title, body, 10_000);
206+
console.log(title, body);
207+
return undefined;
208+
}
209+
}
210+
130211
const getData = async (): Promise<{
131212
workflow: any;
132213
dryrun: any;
@@ -180,12 +261,43 @@
180261
cumulativeNetworkData = result.cumulativeNetworkData;
181262
currentNetworkData = result.currentNetworkData;
182263
logs = result.logs;
264+
const carbontrackerData: Array<{
265+
nodeId: string;
266+
stepName: string;
267+
carbonData: { fetchCarbontrackerData?: { co2eq: number; energy: number } } | undefined;
268+
}> = [];
269+
for (const step of metricsResponse) {
270+
if (step.type === 'Pod') {
271+
const carbonResponse = await getCarbontrackerDataResponse(
272+
step.metrics.cpuUsageSecondsTotal
273+
);
274+
carbontrackerData.push({
275+
nodeId: step.id,
276+
stepName: step.displayName,
277+
carbonData: carbonResponse
278+
});
279+
}
280+
}
281+
282+
// Merge carbontracker data with stepsList
283+
$stepsList = $stepsList.map((step) => {
284+
const carbonData = carbontrackerData.find((carbon) => carbon.nodeId === step.id);
285+
return {
286+
...step,
287+
carbontracker: carbonData ? carbonData.carbonData : undefined
288+
};
289+
});
290+
183291
const responses = {
184292
workflow: workflowResponse.project,
185293
dryrun: dryrunResponse,
186294
metrics: metricsResponse,
187-
allstepnames: allStepNames
295+
allstepnames: allStepNames,
296+
selectedDryRunName: $selectedDryRunName,
297+
carbontrackerData
188298
};
299+
300+
console.log('responses:', responses);
189301
return responses;
190302
};
191303
@@ -496,6 +608,8 @@
496608
<th>Started</th>
497609
<th>Finished</th>
498610
<th>Duration</th>
611+
<th>CO2 [<span class="lowercase">g</span>]</th>
612+
<th>Energy [<span class="lowercase">k</span>Wh]</th>
499613
<th>Status</th>
500614
<th>Output</th>
501615
</tr>
@@ -505,14 +619,28 @@
505619
<!-- eslint-disable-next-line @typescript-eslint/explicit-function-return-type -->
506620
<tr on:click={() => stepOnClick(step.displayName)}>
507621
<td style="width:15%">{step.displayName}</td>
508-
<td style="width:20%">
622+
<td style="width:15%">
509623
{step.startedAt ?? '-'}
510624
</td>
511-
<td style="width:20%">
625+
<td style="width:15%">
512626
{step.finishedAt ?? '-'}
513627
</td>
514-
<td style="width:15%">{displayStepDuration(step)}</td>
515-
<td style="width:15%">{step.phase}</td>
628+
<td style="width:10%">{displayStepDuration(step)}</td>
629+
<td style="width:10%">
630+
{#if step.carbontracker?.fetchCarbontrackerData?.co2eq}
631+
{step.carbontracker.fetchCarbontrackerData.co2eq.toFixed(3)}
632+
{:else}
633+
-
634+
{/if}
635+
</td>
636+
<td style="width:10%">
637+
{#if step.carbontracker?.fetchCarbontrackerData?.energy}
638+
{step.carbontracker.fetchCarbontrackerData.energy.toFixed(6)}
639+
{:else}
640+
-
641+
{/if}
642+
</td>
643+
<td style="width:10%">{step.phase}</td>
516644
<td style="width:15%">
517645
{#if step.outputArtifacts?.length > 1}
518646
{#each step.outputArtifacts as artifact}
@@ -600,8 +728,16 @@
600728
<tr>
601729
<td>Duration</td>
602730
<td> {pipelineDuration} </td>
603-
</tr></tbody
604-
>
731+
</tr>
732+
<tr>
733+
<td>Total CO2</td>
734+
<td> {totalCO2} g </td>
735+
</tr>
736+
<tr>
737+
<td>Total Energy</td>
738+
<td> {totalEnergy} kWh </td>
739+
</tr>
740+
</tbody>
605741
</table>
606742
</div>
607743

frontend/src/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export type DryRun = {
5050
export type DryRunMetrics = {
5151
phase: string;
5252
displayName: string;
53+
id: string;
5354
startedAt: string;
5455
finishedAt: string;
5556
duration: number;

0 commit comments

Comments
 (0)