Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add history and workflow invocation carbon emissions reporting #17542

Open
wants to merge 38 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b2ac178
Implement history carbon emissions reporting (WIP)
Renni771 Feb 2, 2024
6e1d992
Implement carbon emissions reporting for histories and workflow invoc…
Renni771 Feb 20, 2024
6c78cf0
Format code
Renni771 Feb 20, 2024
59902c0
Unify energy usage summary type in API schema
Renni771 Feb 20, 2024
1326742
Estimate server instance when collecting job metrics
Renni771 Feb 20, 2024
3fd2cdb
Calculate job carbon emissions directly using metrics.
Renni771 Feb 21, 2024
9e64c04
Do not display energy usage metrics in job metrics list
Renni771 Feb 21, 2024
bcce348
Clean up carbon emissions client markup and code
Renni771 Feb 21, 2024
4bdee2a
Revert HistoryView component to previous state using options API
Renni771 Feb 21, 2024
dcfdbc8
Use correct props and adjust code style
Renni771 Feb 21, 2024
945fa5b
Update tests
Renni771 Feb 22, 2024
1471dd6
Remove estimated server instance name. Refactor carbon emissions impo…
Renni771 Feb 22, 2024
8bfafec
Add history size to history statistics button
Renni771 Feb 22, 2024
4c635fc
Add types to useCarbonEmissions return values
Renni771 Feb 22, 2024
5c5a546
Add missing component import
Renni771 Feb 22, 2024
d281e44
Refactor CarbonEmissions.vue tests. Adjust and format markup and code
Renni771 Feb 22, 2024
697ec18
Use correct selector in HistoryView component tests
Renni771 Feb 22, 2024
0130d91
Convert snake-cased components to PascalCase ones and import them exp…
Renni771 Feb 22, 2024
f3013e0
Merge branch 'dev' into add-history-carbon-emissions
Renni771 Feb 22, 2024
3526d52
Remove unused imports and fix typing in job_metrics and jobs files
Renni771 Feb 22, 2024
d73ac7e
Remove unnecessary open mode parameters
Renni771 Feb 22, 2024
64fb89b
Update package imports
Renni771 Feb 22, 2024
69158fc
Update exported symbols
Renni771 Feb 22, 2024
409f4d3
Update import statement for load_aws_ec2_reference_data_json
Renni771 Feb 22, 2024
73fc760
Merge branch 'dev' into add-history-carbon-emissions
Renni771 Feb 25, 2024
4ef52c3
Resolve linting issues
Renni771 Feb 26, 2024
cf327d2
Use from typing module
Renni771 Feb 26, 2024
17039c7
Use List from typing module
Renni771 Feb 26, 2024
7e1551c
Remove unused code
Renni771 Feb 26, 2024
79be5f7
Update client API schema
Renni771 Feb 26, 2024
4155963
Combine energy usage query into a single one
Renni771 Feb 27, 2024
ad7bec1
Merge branch 'dev' into add-history-and-workflow-invocation-carbon-em…
Renni771 Feb 29, 2024
0d51f95
Update energy usage summary model and API endpoints
Renni771 Mar 4, 2024
399da83
Merge branch 'dev' into add-history-and-workflow-invocation-carbon-em…
Renni771 Mar 4, 2024
e8e7ace
Remove duplicate import
Renni771 Mar 5, 2024
3fd33f4
Remove use of TypedDict to support python 3.5.
Renni771 Mar 5, 2024
5a1a610
Only show carbon emissions reports when enabled in config
Renni771 Mar 5, 2024
c4919ea
Exclude energy usage flags from core plugin formatter
Renni771 Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions client/src/api/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,13 @@ export interface paths {
/** Materialize a deferred library or HDA dataset into real, usable dataset in specified history. */
post: operations["materialize_to_history_api_histories__history_id__materialize_post"];
};
"/api/histories/{history_id}/metrics": {
/**
* Get the cumulative metrics of all jobs in a given history.
* @description Get the cumulative metrics of all jobs in a history with ``history_id``.
*/
get: operations["get_metrics_api_histories__history_id__metrics_get"];
};
"/api/histories/{history_id}/prepare_store_download": {
/** Return a short term storage token to monitor download of the history. */
post: operations["prepare_store_download_api_histories__history_id__prepare_store_download_post"];
Expand Down Expand Up @@ -1000,6 +1007,13 @@ export interface paths {
*/
get: operations["invocation_jobs_summary_api_invocations__invocation_id__jobs_summary_get"];
};
"/api/invocations/{invocation_id}/metrics": {
/**
* Get the cumulative metrics of all jobs in a given workflow invocation.
* @description Get the cumulative metrics of all jobs in a workflow invocation with ``invocation_id``.
*/
get: operations["get_metrics_api_invocations__invocation_id__metrics_get"];
};
"/api/invocations/{invocation_id}/prepare_store_download": {
/** Prepare a workflow invocation export-style download. */
post: operations["prepare_store_download_api_invocations__invocation_id__prepare_store_download_post"];
Expand Down Expand Up @@ -8957,6 +8971,21 @@ export interface components {
*/
time: string;
};
/** MetricsSummaryCumulative */
MetricsSummaryCumulative: {
/** Total Allocated Cores Cpu */
total_allocated_cores_cpu: number;
/** Total Allocated Memory Mebibyte */
total_allocated_memory_mebibyte: number;
/** Total Energy Needed Cpu Kwh */
total_energy_needed_cpu_kwh: number;
/** Total Energy Needed Kwh */
total_energy_needed_kwh: number;
/** Total Energy Needed Memory Kwh */
total_energy_needed_memory_kwh: number;
Comment on lines +8980 to +8985
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move that into another model ?

Copy link
Contributor Author

@Renni771 Renni771 Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have something like this in mind?:

# lib/galaxy/schema/schema.py

class MetricsSummaryEnergyCumulative(Model):
    total_energy_needed_cpu_kwh: float
    total_energy_needed_memory_kwh: float
    total_energy_needed_kwh: float

class MetricsSummaryCoreCumulative(Model):
    total_allocated_cores_cpu: int
    total_allocated_memory_mebibyte: int
    total_runtime_seconds: int
    energy_usage_metrics: Optional[MetricsSummaryEnergyCumulative]

/** Total Runtime Seconds */
total_runtime_seconds: number;
};
/**
* ModelStoreFormat
* @description Available types of model stores for export.
Expand Down Expand Up @@ -17496,6 +17525,36 @@ export interface operations {
};
};
};
get_metrics_api_histories__history_id__metrics_get: {
/**
* Get the cumulative metrics of all jobs in a given history.
* @description Get the cumulative metrics of all jobs in a history with ``history_id``.
*/
parameters: {
/** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */
header?: {
"run-as"?: string | null;
};
/** @description The encoded database identifier of the History. */
path: {
history_id: string;
};
};
responses: {
/** @description Successful Response */
200: {
content: {
"application/json": components["schemas"]["MetricsSummaryCumulative"];
};
};
/** @description Validation Error */
422: {
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
prepare_store_download_api_histories__history_id__prepare_store_download_post: {
/** Return a short term storage token to monitor download of the history. */
parameters: {
Expand Down Expand Up @@ -18171,6 +18230,36 @@ export interface operations {
};
};
};
get_metrics_api_invocations__invocation_id__metrics_get: {
/**
* Get the cumulative metrics of all jobs in a given workflow invocation.
* @description Get the cumulative metrics of all jobs in a workflow invocation with ``invocation_id``.
*/
parameters: {
/** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */
header?: {
"run-as"?: string | null;
};
/** @description The encoded database identifier of the Invocation. */
path: {
invocation_id: string;
};
};
responses: {
/** @description Successful Response */
200: {
content: {
"application/json": components["schemas"]["MetricsSummaryCumulative"];
};
};
/** @description Validation Error */
422: {
content: {
"application/json": components["schemas"]["HTTPValidationError"];
};
};
};
};
prepare_store_download_api_invocations__invocation_id__prepare_store_download_post: {
/** Prepare a workflow invocation export-style download. */
parameters: {
Expand Down
84 changes: 84 additions & 0 deletions client/src/components/CarbonEmissions/CarbonEmissions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { createTestingPinia } from "@pinia/testing";
import { mount } from "@vue/test-utils";
import { getLocalVue } from "tests/jest/helpers";
import { ref } from "vue";

import { worldwideCarbonIntensity } from "./carbonEmissionConstants";

import CarbonEmissions from "./CarbonEmissions.vue";

const carbonIntensity = ref(worldwideCarbonIntensity);
const geographicalServerLocationName = ref("GLOBAL");
jest.mock("@/composables/carbonEmissions", () => ({
useCarbonEmissions: () => {
return {
carbonIntensity,
geographicalServerLocationName,
};
},
}));

const localVue = getLocalVue();
const pinia = createTestingPinia();
const slots = {
header: "<div>foo</div>",
footer: "<div>bar</div>",
};

describe("CarbonEmissions/CarbonEmissions.vue", () => {
it("correctly calculates carbon emissions.", () => {
const wrapper = mount(CarbonEmissions as any, {
propsData: {
energyNeededCPU: 0.015,
energyNeededMemory: 0.005,
},
pinia,
slots,
localVue,
});

const cpuEmissions = wrapper.find("#cpu-carbon-emissions").text();
const memoryEmissions = wrapper.find("#memory-carbon-emissions").text();
const cpuEnergyUsage = wrapper.find("#cpu-energy-usage").text();
const memoryEnergyUsage = wrapper.find("#memory-energy-usage").text();

expect(cpuEmissions).toMatch("7 g CO2e");
expect(memoryEmissions).toMatch("2 g CO2e");
expect(cpuEnergyUsage).toMatch("15 mW⋅h");
expect(memoryEnergyUsage).toMatch("5 mW⋅h");
});

it("does not render any data for memory if its memroy usage is 0.", () => {
const wrapper = mount(CarbonEmissions as any, {
propsData: {
energyNeededCPU: 0,
energyNeededMemory: 0,
},
pinia,
slots,
localVue,
});

expect(wrapper.find("#memory-energy-usage").exists()).toBe(false);
expect(wrapper.find("#memroy-carbon-emissions").exists()).toBe(false);
});

it("takes the configured `carbonIntensity` value into account.", () => {
carbonIntensity.value = 0;
const wrapper = mount(CarbonEmissions as any, {
propsData: {
energyNeededCPU: 1_000,
energyNeededMemory: 1_000,
},
pinia,
slots,
localVue,
});

const cpuEmissions = wrapper.find("#cpu-carbon-emissions").text();
const memoryEmissions = wrapper.find("#memory-carbon-emissions").text();

expect(cpuEmissions).toMatch("0 g CO2e");
expect(memoryEmissions).toMatch("0 g CO2e");
});
});
Loading
Loading