From b69122138f5f7bb068f4e4a5add6916ceec8121a Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Mon, 26 Oct 2026 11:57:06 +0000 Subject: [PATCH 1/7] Initial commit for Real Time Cloud data data source --- .../RealTimeCloud/v1/configValidation.json | 11 + plugins/RealTimeCloud/v1/cspell.json | 10 + plugins/RealTimeCloud/v1/custom_types.json | 9 + .../v1/dataStreams/regionEstimates.json | 293 ++++++++ .../v1/dataStreams/regionMetadata.json | 304 +++++++++ .../RealTimeCloud/v1/dataStreams/regions.json | 39 ++ .../v1/dataStreams/scripts/regionEstimates.js | 96 +++ .../v1/dataStreams/scripts/regionMetadata.js | 108 +++ .../v1/dataStreams/scripts/regions.js | 71 ++ .../defaultContent/carbonIntensity.dash.json | 413 ++++++++++++ .../v1/defaultContent/cloudRegion.dash.json | 629 ++++++++++++++++++ .../v1/defaultContent/efficiency.dash.json | 505 ++++++++++++++ .../v1/defaultContent/manifest.json | 20 + .../v1/defaultContent/overview.dash.json | 289 ++++++++ .../v1/defaultContent/scopes.json | 19 + plugins/RealTimeCloud/v1/docs/README.md | 52 ++ plugins/RealTimeCloud/v1/icon.svg | 1 + .../v1/indexDefinitions/default.json | 24 + plugins/RealTimeCloud/v1/metadata.json | 51 ++ plugins/RealTimeCloud/v1/ui.json | 1 + 20 files changed, 2945 insertions(+) create mode 100644 plugins/RealTimeCloud/v1/configValidation.json create mode 100644 plugins/RealTimeCloud/v1/cspell.json create mode 100644 plugins/RealTimeCloud/v1/custom_types.json create mode 100644 plugins/RealTimeCloud/v1/dataStreams/regionEstimates.json create mode 100644 plugins/RealTimeCloud/v1/dataStreams/regionMetadata.json create mode 100644 plugins/RealTimeCloud/v1/dataStreams/regions.json create mode 100644 plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js create mode 100644 plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js create mode 100644 plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js create mode 100644 plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json create mode 100644 plugins/RealTimeCloud/v1/defaultContent/cloudRegion.dash.json create mode 100644 plugins/RealTimeCloud/v1/defaultContent/efficiency.dash.json create mode 100644 plugins/RealTimeCloud/v1/defaultContent/manifest.json create mode 100644 plugins/RealTimeCloud/v1/defaultContent/overview.dash.json create mode 100644 plugins/RealTimeCloud/v1/defaultContent/scopes.json create mode 100644 plugins/RealTimeCloud/v1/docs/README.md create mode 100644 plugins/RealTimeCloud/v1/icon.svg create mode 100644 plugins/RealTimeCloud/v1/indexDefinitions/default.json create mode 100644 plugins/RealTimeCloud/v1/metadata.json create mode 100644 plugins/RealTimeCloud/v1/ui.json diff --git a/plugins/RealTimeCloud/v1/configValidation.json b/plugins/RealTimeCloud/v1/configValidation.json new file mode 100644 index 00000000..da948cf6 --- /dev/null +++ b/plugins/RealTimeCloud/v1/configValidation.json @@ -0,0 +1,11 @@ +{ + "steps": [ + { + "displayName": "Region metadata", + "dataStream": { "name": "regions" }, + "success": "Region metadata found", + "error": "Could not read Cloud_Region_Metadata.csv — Green Software Foundation may be unreachable", + "required": true + } + ] +} diff --git a/plugins/RealTimeCloud/v1/cspell.json b/plugins/RealTimeCloud/v1/cspell.json new file mode 100644 index 00000000..f1b6af8f --- /dev/null +++ b/plugins/RealTimeCloud/v1/cspell.json @@ -0,0 +1,10 @@ +{ + "words": [ + "WUE", + "CFE", + "gCO₂eq", + "WattTime", + "Electricity Maps", + "greensoftware" + ] +} diff --git a/plugins/RealTimeCloud/v1/custom_types.json b/plugins/RealTimeCloud/v1/custom_types.json new file mode 100644 index 00000000..5f21ac3e --- /dev/null +++ b/plugins/RealTimeCloud/v1/custom_types.json @@ -0,0 +1,9 @@ +[ + { + "name": "Cloud Region", + "sourceType": "Cloud Region", + "icon": "cloud", + "singular": "Cloud Region", + "plural": "Cloud Regions" + } +] diff --git a/plugins/RealTimeCloud/v1/dataStreams/regionEstimates.json b/plugins/RealTimeCloud/v1/dataStreams/regionEstimates.json new file mode 100644 index 00000000..5122c0e5 --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/regionEstimates.json @@ -0,0 +1,293 @@ +{ + "name": "regionEstimates", + "displayName": "Region Estimates", + "description": "Estimated annual sustainability metrics per cloud region, trended from provider-disclosed data", + "tags": [ + "Sustainability", + "Cloud" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "Cloud_Region_Metadata_estimate.csv", + "paging": { + "mode": "none" + }, + "postRequestScript": "regionEstimates.js" + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "region", + "label": "Cloud region (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Cloud Region" + ] + } + } + } + ], + "metadata": [ + { + "name": "year", + "displayName": "Year", + "shape": [ + "number", + { + "thousandsSeparator": false + } + ] + }, + { + "name": "regionId", + "displayName": "Region ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "regionId", + "sourceType": "Cloud Region", + "name": "region" + }, + { + "name": "region", + "displayName": "Region", + "shape": "string", + "role": "label" + }, + { + "name": "provider", + "displayName": "Provider", + "shape": "string" + }, + { + "name": "location", + "displayName": "Location", + "shape": "string" + }, + { + "name": "cfeRegion", + "displayName": "CFE Region", + "shape": "string" + }, + { + "name": "emZoneId", + "displayName": "Electricity Maps Zone", + "shape": "string" + }, + { + "name": "wtRegionId", + "displayName": "WattTime Region", + "shape": "string" + }, + { + "name": "latitude", + "displayName": "Latitude", + "shape": [ + "number", + { + "decimalPlaces": 4 + } + ] + }, + { + "name": "longitude", + "displayName": "Longitude", + "shape": [ + "number", + { + "decimalPlaces": 4 + } + ] + }, + { + "name": "providerCfeHourly", + "displayName": "Provider CFE (hourly)", + "shape": [ + "percent", + { + "asZeroToOne": true, + "decimalPlaces": 1 + } + ] + }, + { + "name": "providerCfeAnnual", + "displayName": "Provider CFE (annual)", + "shape": [ + "percent", + { + "asZeroToOne": true, + "decimalPlaces": 1 + } + ] + }, + { + "name": "pue", + "displayName": "PUE", + "shape": [ + "number", + { + "decimalPlaces": 2 + } + ], + "role": "value" + }, + { + "name": "wue", + "displayName": "WUE (L/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 2 + } + ] + }, + { + "name": "providerCarbonIntensityMarketAnnual", + "displayName": "Provider carbon intensity (market, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "providerCarbonIntensityConsumptionHourly", + "displayName": "Provider carbon intensity (consumption, hourly) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityConsumptionAnnual", + "displayName": "Grid carbon intensity (consumption, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityMarginalAnnual", + "displayName": "Grid carbon intensity (marginal, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityProductionAnnual", + "displayName": "Grid carbon intensity (production, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensity", + "displayName": "Grid carbon intensity (SCI-o) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "totalEnergyKwh", + "visible": false, + "displayName": "Total ICT energy (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "totalWaterInputLitres", + "displayName": "Total water input (L)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyKwh", + "visible": false, + "displayName": "Renewable energy (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyGooKwh", + "visible": false, + "displayName": "Renewable energy (GoO/REC) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyPpaKwh", + "visible": false, + "displayName": "Renewable energy (PPA) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyOnsiteKwh", + "visible": false, + "displayName": "Renewable energy (on-site) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + } + ], + "defaultShaping": { + "sort": { + "by": [ + [ + "year", + "desc" + ] + ] + } + }, + "timeframes": false +} diff --git a/plugins/RealTimeCloud/v1/dataStreams/regionMetadata.json b/plugins/RealTimeCloud/v1/dataStreams/regionMetadata.json new file mode 100644 index 00000000..2f5484be --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/regionMetadata.json @@ -0,0 +1,304 @@ +{ + "name": "regionMetadata", + "displayName": "Region Metadata", + "description": "Provider-disclosed annual sustainability metrics per cloud region, one row per region per year", + "tags": [ + "Sustainability", + "Cloud" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "Cloud_Region_Metadata.csv", + "paging": { + "mode": "none" + }, + "postRequestScript": "regionMetadata.js" + }, + "matches": "none", + "ui": [ + { + "type": "objects", + "name": "region", + "label": "Cloud region (optional)", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Cloud Region" + ] + } + } + } + ], + "metadata": [ + { + "name": "year", + "displayName": "Year", + "shape": [ + "number", + { + "thousandsSeparator": false + } + ] + }, + { + "name": "isLatest", + "displayName": "Latest year for region", + "shape": [ + "number", + { + "thousandsSeparator": false + } + ], + "visible": false + }, + { + "name": "regionId", + "displayName": "Region ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "regionId", + "sourceType": "Cloud Region", + "name": "region" + }, + { + "name": "region", + "displayName": "Region", + "shape": "string", + "role": "label" + }, + { + "name": "provider", + "displayName": "Provider", + "shape": "string" + }, + { + "name": "location", + "displayName": "Location", + "shape": "string" + }, + { + "name": "cfeRegion", + "displayName": "CFE Region", + "shape": "string" + }, + { + "name": "emZoneId", + "displayName": "Electricity Maps Zone", + "shape": "string" + }, + { + "name": "wtRegionId", + "displayName": "WattTime Region", + "shape": "string" + }, + { + "name": "latitude", + "displayName": "Latitude", + "shape": [ + "number", + { + "decimalPlaces": 4 + } + ] + }, + { + "name": "longitude", + "displayName": "Longitude", + "shape": [ + "number", + { + "decimalPlaces": 4 + } + ] + }, + { + "name": "providerCfeHourly", + "displayName": "Provider CFE (hourly)", + "shape": [ + "percent", + { + "asZeroToOne": true, + "decimalPlaces": 1 + } + ] + }, + { + "name": "providerCfeAnnual", + "displayName": "Provider CFE (annual)", + "shape": [ + "percent", + { + "asZeroToOne": true, + "decimalPlaces": 1 + } + ] + }, + { + "name": "pue", + "displayName": "PUE", + "shape": [ + "number", + { + "decimalPlaces": 2 + } + ], + "role": "value" + }, + { + "name": "wue", + "displayName": "WUE (L/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 2 + } + ] + }, + { + "name": "providerCarbonIntensityMarketAnnual", + "displayName": "Provider carbon intensity (market, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "providerCarbonIntensityConsumptionHourly", + "displayName": "Provider carbon intensity (consumption, hourly) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityConsumptionAnnual", + "displayName": "Grid carbon intensity (consumption, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityMarginalAnnual", + "displayName": "Grid carbon intensity (marginal, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensityProductionAnnual", + "displayName": "Grid carbon intensity (production, annual) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "gridCarbonIntensity", + "displayName": "Grid carbon intensity (SCI-o) (gCO₂eq/kWh)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "totalEnergyKwh", + "visible": false, + "displayName": "Total ICT energy (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "totalWaterInputLitres", + "displayName": "Total water input (L)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyKwh", + "visible": false, + "displayName": "Renewable energy (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyGooKwh", + "visible": false, + "displayName": "Renewable energy (GoO/REC) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyPpaKwh", + "visible": false, + "displayName": "Renewable energy (PPA) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + }, + { + "name": "renewableEnergyOnsiteKwh", + "visible": false, + "displayName": "Renewable energy (on-site) (kWh)", + "shape": [ + "number", + { + "thousandsSeparator": true, + "decimalPlaces": 0 + } + ] + } + ], + "defaultShaping": { + "sort": { + "by": [ + [ + "year", + "desc" + ] + ] + } + }, + "timeframes": false +} diff --git a/plugins/RealTimeCloud/v1/dataStreams/regions.json b/plugins/RealTimeCloud/v1/dataStreams/regions.json new file mode 100644 index 00000000..d9c6a960 --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/regions.json @@ -0,0 +1,39 @@ +{ + "name": "regions", + "displayName": "Regions", + "description": "Cloud regions listed in the region metadata, one row per provider and region", + "tags": [ + "Cloud" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "Cloud_Region_Metadata.csv", + "paging": { + "mode": "none" + }, + "postRequestScript": "regions.js" + }, + "matches": "none", + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "regionId", + "displayName": "Region ID", + "shape": "string", + "role": "id" + }, + { + "name": "name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "pattern": ".*" + } + ], + "timeframes": false +} diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js new file mode 100644 index 00000000..3ed090be --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js @@ -0,0 +1,96 @@ +const parseCsv = (text) => { + const rows = []; + let row = []; + let field = ""; + let quoted = false; + const src = text.replace(/^/, ""); + for (let i = 0; i < src.length; i++) { + const c = src[i]; + if (quoted) { + if (c === '"' && src[i + 1] === '"') { + field += '"'; + i++; + } else if (c === '"') quoted = false; + else field += c; + } else if (c === '"') quoted = true; + else if (c === ",") { + row.push(field); + field = ""; + } else if (c === "\n" || c === "\r") { + if (c === "\r" && src[i + 1] === "\n") i++; + row.push(field); + field = ""; + if (row.length > 1 || row[0] !== "") rows.push(row); + row = []; + } else field += c; + } + if (field !== "" || row.length) { + row.push(field); + rows.push(row); + } + const header = rows.shift().map((h) => h.trim()); + return rows.map((r) => + Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), + ); +}; +const num = (v) => + v === "" || v.toUpperCase() === "NA" + ? null + : Number.isFinite(Number(v)) + ? Number(v) + : null; +const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const geo = (v) => { + const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); + return { latitude: lat ?? null, longitude: lon ?? null }; +}; + +// Optional `region` object picker: selected objects arrive as an array, each rawId a single-element array. +const unwrap = (v) => (Array.isArray(v) ? v[0] : v); +const selected = (context.config && context.config.region) || []; +const ids = new Set(selected.map((o) => unwrap(o.rawId)).filter(Boolean)); + +result = parseCsv(response.body) + .filter((r) => r["cloud-provider"] && r["cloud-region"]) + .filter( + (r) => + !ids.size || + ids.has(`${r["cloud-provider"]}/${r["cloud-region"]}`), + ) + .map((r) => ({ + year: num(r.year), + regionId: `${r["cloud-provider"]}/${r["cloud-region"]}`, + provider: r["cloud-provider"], + region: r["cloud-region"], + location: str(r.location), + cfeRegion: str(r["cfe-region"]), + emZoneId: str(r["em-zone-id"]), + wtRegionId: str(r["wt-region-id"]), + ...geo(r.geolocation), + providerCfeHourly: num(r["provider-cfe-hourly"]), + providerCfeAnnual: num(r["provider-cfe-annual"]), + pue: num(r["power-usage-effectiveness"]), + wue: num(r["water-usage-effectiveness"]), + providerCarbonIntensityMarketAnnual: num( + r["provider-carbon-intensity-market-annual"], + ), + providerCarbonIntensityConsumptionHourly: num( + r["provider-carbon-intensity-average-consumption-hourly"], + ), + gridCarbonIntensityConsumptionAnnual: num( + r["grid-carbon-intensity-average-consumption-annual"], + ), + gridCarbonIntensityMarginalAnnual: num( + r["grid-carbon-intensity-marginal-consumption-annual"], + ), + gridCarbonIntensityProductionAnnual: num( + r["grid-carbon-intensity-average-production-annual"], + ), + gridCarbonIntensity: num(r["grid-carbon-intensity"]), + totalEnergyKwh: num(r["total-ICT-energy-consumption-annual"]), + totalWaterInputLitres: num(r["total-water-input"]), + renewableEnergyKwh: num(r["renewable-energy-consumption"]), + renewableEnergyGooKwh: num(r["renewable-energy-consumption-goe"]), + renewableEnergyPpaKwh: num(r["renewable-energy-consumption-ppa"]), + renewableEnergyOnsiteKwh: num(r["renewable-energy-consumption-onsite"]), + })); diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js new file mode 100644 index 00000000..e51dbdd2 --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js @@ -0,0 +1,108 @@ +const parseCsv = (text) => { + const rows = []; + let row = []; + let field = ""; + let quoted = false; + const src = text.replace(/^/, ""); + for (let i = 0; i < src.length; i++) { + const c = src[i]; + if (quoted) { + if (c === '"' && src[i + 1] === '"') { + field += '"'; + i++; + } else if (c === '"') quoted = false; + else field += c; + } else if (c === '"') quoted = true; + else if (c === ",") { + row.push(field); + field = ""; + } else if (c === "\n" || c === "\r") { + if (c === "\r" && src[i + 1] === "\n") i++; + row.push(field); + field = ""; + if (row.length > 1 || row[0] !== "") rows.push(row); + row = []; + } else field += c; + } + if (field !== "" || row.length) { + row.push(field); + rows.push(row); + } + const header = rows.shift().map((h) => h.trim()); + return rows.map((r) => + Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), + ); +}; +const num = (v) => + v === "" || v.toUpperCase() === "NA" + ? null + : Number.isFinite(Number(v)) + ? Number(v) + : null; +const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const geo = (v) => { + const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); + return { latitude: lat ?? null, longitude: lon ?? null }; +}; + +// Optional `region` object picker: selected objects arrive as an array, each rawId a single-element array. +const unwrap = (v) => (Array.isArray(v) ? v[0] : v); +const selected = (context.config && context.config.region) || []; +const ids = new Set(selected.map((o) => unwrap(o.rawId)).filter(Boolean)); + +const rows = parseCsv(response.body).filter( + (r) => r["cloud-provider"] && r["cloud-region"], +); +const latestYear = {}; +for (const r of rows) { + const id = `${r["cloud-provider"]}/${r["cloud-region"]}`; + latestYear[id] = Math.max(latestYear[id] ?? -Infinity, num(r.year) ?? -Infinity); +} + +result = rows + .filter( + (r) => + !ids.size || + ids.has(`${r["cloud-provider"]}/${r["cloud-region"]}`), + ) + .map((r) => ({ + year: num(r.year), + isLatest: + num(r.year) === latestYear[`${r["cloud-provider"]}/${r["cloud-region"]}`] + ? 1 + : 0, + regionId: `${r["cloud-provider"]}/${r["cloud-region"]}`, + provider: r["cloud-provider"], + region: r["cloud-region"], + location: str(r.location), + cfeRegion: str(r["cfe-region"]), + emZoneId: str(r["em-zone-id"]), + wtRegionId: str(r["wt-region-id"]), + ...geo(r.geolocation), + providerCfeHourly: num(r["provider-cfe-hourly"]), + providerCfeAnnual: num(r["provider-cfe-annual"]), + pue: num(r["power-usage-effectiveness"]), + wue: num(r["water-usage-effectiveness"]), + providerCarbonIntensityMarketAnnual: num( + r["provider-carbon-intensity-market-annual"], + ), + providerCarbonIntensityConsumptionHourly: num( + r["provider-carbon-intensity-average-consumption-hourly"], + ), + gridCarbonIntensityConsumptionAnnual: num( + r["grid-carbon-intensity-average-consumption-annual"], + ), + gridCarbonIntensityMarginalAnnual: num( + r["grid-carbon-intensity-marginal-consumption-annual"], + ), + gridCarbonIntensityProductionAnnual: num( + r["grid-carbon-intensity-average-production-annual"], + ), + gridCarbonIntensity: num(r["grid-carbon-intensity"]), + totalEnergyKwh: num(r["total-ICT-energy-consumption-annual"]), + totalWaterInputLitres: num(r["total-water-input"]), + renewableEnergyKwh: num(r["renewable-energy-consumption"]), + renewableEnergyGooKwh: num(r["renewable-energy-consumption-goe"]), + renewableEnergyPpaKwh: num(r["renewable-energy-consumption-ppa"]), + renewableEnergyOnsiteKwh: num(r["renewable-energy-consumption-onsite"]), + })); diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js new file mode 100644 index 00000000..24df0de7 --- /dev/null +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js @@ -0,0 +1,71 @@ +const parseCsv = (text) => { + const rows = []; + let row = []; + let field = ""; + let quoted = false; + const src = text.replace(/^/, ""); + for (let i = 0; i < src.length; i++) { + const c = src[i]; + if (quoted) { + if (c === '"' && src[i + 1] === '"') { + field += '"'; + i++; + } else if (c === '"') quoted = false; + else field += c; + } else if (c === '"') quoted = true; + else if (c === ",") { + row.push(field); + field = ""; + } else if (c === "\n" || c === "\r") { + if (c === "\r" && src[i + 1] === "\n") i++; + row.push(field); + field = ""; + if (row.length > 1 || row[0] !== "") rows.push(row); + row = []; + } else field += c; + } + if (field !== "" || row.length) { + row.push(field); + rows.push(row); + } + const header = rows.shift().map((h) => h.trim()); + return rows.map((r) => + Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), + ); +}; +const num = (v) => + v === "" || v.toUpperCase() === "NA" + ? null + : Number.isFinite(Number(v)) + ? Number(v) + : null; +const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const geo = (v) => { + const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); + return { latitude: lat ?? null, longitude: lon ?? null }; +}; + +const seen = new Set(); +result = parseCsv(response.body) + .filter((r) => r["cloud-provider"] && r["cloud-region"]) + .sort((a, b) => Number(b.year) - Number(a.year)) + .flatMap((r) => { + const provider = r["cloud-provider"]; + const region = r["cloud-region"]; + const regionId = `${provider}/${region}`; + if (seen.has(regionId)) return []; + seen.add(regionId); + return [ + { + regionId, + name: `${region} (${provider})`, + provider, + region, + location: str(r.location), + cfeRegion: str(r["cfe-region"]), + emZoneId: str(r["em-zone-id"]), + wtRegionId: str(r["wt-region-id"]), + ...geo(r.geolocation), + }, + ]; + }); diff --git a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json new file mode 100644 index 00000000..dbcc3110 --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json @@ -0,0 +1,413 @@ +{ + "name": "Carbon Intensity", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "dc1d4f65-5e27-4f62-9998-d60ca24b7999", + "x": 0, + "y": 0, + "w": 4, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Grid carbon intensity summary", + "description": "Grid carbon intensity (consumption, annual) across all regions, latest disclosed year", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT COUNT(*) FILTER (WHERE \"gridCarbonIntensityConsumptionAnnual\" < 100) AS \"lowCarbonRegions\", ROUND(MIN(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"minCi\", ROUND(MEDIAN(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"medianCi\", ROUND(MAX(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"maxCi\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"gridCarbonIntensityConsumptionAnnual\" IS NOT NULL" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "lowCarbonRegions", + "type": "quantitative", + "title": "Low-carbon regions (<100 g/kWh)" + }, + { + "field": "minCi", + "type": "quantitative", + "title": "Cleanest region (gCO₂eq/kWh)" + }, + { + "field": "medianCi", + "type": "quantitative", + "title": "Median region (gCO₂eq/kWh)" + }, + { + "field": "maxCi", + "type": "quantitative", + "title": "Dirtiest region (gCO₂eq/kWh)" + } + ] + }, + "style": { + "scalarColumns": 4 + } + } + } + } + }, + { + "i": "80f101ed-8b95-4e8f-b809-57f632dded2d", + "x": 0, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "15 cleanest regions", + "description": "Lowest grid carbon intensity (gCO₂eq/kWh), latest disclosed year", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\" || ' · ' || CASE \"provider\" WHEN 'Amazon Web Services' THEN 'AWS' WHEN 'Google Cloud' THEN 'GCP' WHEN 'Microsoft Azure' THEN 'Azure' ELSE \"provider\" END AS \"regionLabel\", \"provider\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"gridCarbonIntensityConsumptionAnnual\" IS NOT NULL ORDER BY \"gridCarbonIntensityConsumptionAnnual\" ASC LIMIT 15" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "regionLabel", + "type": "nominal", + "title": "Region" + }, + "y": { + "field": "gridCi", + "type": "quantitative", + "title": "Grid carbon intensity (gCO₂eq/kWh)" + } + }, + "style": { + "cartesianHorizontal": true, + "showLabels": true, + "cartesianBarBorderRadius": 4, + "cartesianShowHorizontalGridLines": false, + "cartesianColorRules": [ + { + "lt": 100, + "color": "#16A34A" + }, + { + "lt": 400, + "color": "#F59E0B" + }, + { + "gte": 400, + "color": "#DC2626" + } + ] + } + } + } + } + }, + { + "i": "8e87b144-fecb-492c-8573-651e4367d281", + "x": 2, + "y": 2, + "w": 2, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "15 highest-carbon regions", + "description": "Highest grid carbon intensity (gCO₂eq/kWh), latest disclosed year", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\" || ' · ' || CASE \"provider\" WHEN 'Amazon Web Services' THEN 'AWS' WHEN 'Google Cloud' THEN 'GCP' WHEN 'Microsoft Azure' THEN 'Azure' ELSE \"provider\" END AS \"regionLabel\", \"provider\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"gridCarbonIntensityConsumptionAnnual\" IS NOT NULL ORDER BY \"gridCarbonIntensityConsumptionAnnual\" DESC LIMIT 15" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "regionLabel", + "type": "nominal", + "title": "Region" + }, + "y": { + "field": "gridCi", + "type": "quantitative", + "title": "Grid carbon intensity (gCO₂eq/kWh)" + } + }, + "style": { + "cartesianHorizontal": true, + "showLabels": true, + "cartesianBarBorderRadius": 4, + "cartesianShowHorizontalGridLines": false, + "cartesianColorRules": [ + { + "lt": 100, + "color": "#16A34A" + }, + { + "lt": 400, + "color": "#F59E0B" + }, + { + "gte": 400, + "color": "#DC2626" + } + ] + } + } + } + } + }, + { + "i": "a48f31cf-1679-4bb7-93ac-ea8667afa63a", + "x": 0, + "y": 6, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Grid carbon intensity trend by provider", + "description": "Mean regional grid carbon intensity per year. Disclosed values, then estimates for years after each provider's latest disclosure.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "datastream-sql", + "dataSourceConfig": { + "version": "2.0", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensityConsumptionAnnual\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "tables": [ + { + "tableName": "hist", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + }, + { + "tableName": "est", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionEstimates]}}", + "name": "regionEstimates", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + } + ] + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "yearLabel", + "type": "nominal", + "title": "Year" + }, + "y": { + "field": "avgGridCi", + "type": "quantitative", + "title": "Avg grid carbon intensity (gCO₂eq/kWh)" + }, + "series": { + "field": "provider", + "type": "nominal" + } + }, + "style": { + "cartesianSmooth": true, + "legendPosition": "bottom", + "cartesianPointRadius": 4, + "mappedColors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + }, + "cartesianAreaGradient": true + } + } + } + } + }, + { + "i": "4095a079-1f3c-40dd-8f29-c778c802d7ed", + "x": 0, + "y": 9, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "All regions – carbon detail", + "description": "Carbon intensity values in gCO₂eq/kWh. Hourly CFE is the share of hourly carbon-free energy reported by the provider. Latest disclosed year.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\", \"provider\", \"location\", CAST(\"year\" AS INTEGER) AS \"year\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\", ROUND(\"gridCarbonIntensityMarginalAnnual\", 0) AS \"marginalCi\", ROUND(\"providerCarbonIntensityConsumptionHourly\", 0) AS \"providerCi\", ROUND(\"providerCfeHourly\" * 100, 0) AS \"cfePct\" FROM \"dataset\" WHERE \"isLatest\" = 1 ORDER BY \"gridCarbonIntensityConsumptionAnnual\" ASC NULLS LAST" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "region", + "title": "Region", + "renderer": { + "type": "text" + } + }, + { + "field": "provider", + "title": "Provider", + "renderer": { + "type": "badge", + "colors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + } + } + }, + { + "field": "location", + "title": "Location", + "renderer": { + "type": "text" + } + }, + { + "field": "year", + "title": "Year", + "renderer": { + "type": "number", + "decimals": 0 + }, + "align": "right" + }, + { + "field": "gridCi", + "title": "Grid CI (consumption)", + "renderer": { + "type": "number", + "decimals": 0, + "thresholds": [ + { + "to": 100, + "color": "#16A34A" + }, + { + "to": 400, + "color": "#F59E0B" + }, + { + "to": 100000, + "color": "#DC2626" + } + ] + }, + "align": "right" + }, + { + "field": "marginalCi", + "title": "Grid CI (marginal)", + "renderer": { + "type": "number", + "decimals": 0 + }, + "align": "right" + }, + { + "field": "providerCi", + "title": "Provider CI (hourly)", + "renderer": { + "type": "number", + "decimals": 0 + }, + "align": "right" + }, + { + "field": "cfePct", + "title": "Hourly CFE", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + }, + "style": { + "richTableSort": { + "field": "gridCi", + "direction": "asc" + }, + "richTableCellPadding": 6, + "richTableAltRowColor": "rgba(148,163,184,0.08)" + } + } + } + } + } + ] + } +} diff --git a/plugins/RealTimeCloud/v1/defaultContent/cloudRegion.dash.json b/plugins/RealTimeCloud/v1/defaultContent/cloudRegion.dash.json new file mode 100644 index 00000000..b95edcd4 --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/cloudRegion.dash.json @@ -0,0 +1,629 @@ +{ + "name": "Cloud Region", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "63f7ac31-33db-4e89-b08b-6067ba106dee", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Latest PUE", + "description": "", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "pue", + "operation": "notempty" + } + ] + }, + "sort": { + "by": [ + [ + "year", + "desc" + ] + ], + "top": 1 + }, + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + } + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "pue", + "type": "quantitative", + "title": "PUE" + } + ] + } + } + } + } + }, + { + "i": "fbc9d90b-a7a7-41af-ae5c-2c70988775c2", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Latest WUE", + "description": "", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "wue", + "operation": "notempty" + } + ] + }, + "sort": { + "by": [ + [ + "year", + "desc" + ] + ], + "top": 1 + }, + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + } + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "wue", + "type": "quantitative", + "title": "WUE (L/kWh)" + } + ] + } + } + } + } + }, + { + "i": "755c63d7-2756-485c-9825-0a70a617b391", + "x": 2, + "y": 0, + "w": 2, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Latest Grid Carbon Intensity", + "description": "", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "gridCarbonIntensityConsumptionAnnual", + "operation": "notempty" + } + ] + }, + "sort": { + "by": [ + [ + "year", + "desc" + ] + ], + "top": 1 + }, + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + } + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "gridCarbonIntensityConsumptionAnnual", + "type": "quantitative", + "title": "gCO₂eq/kWh" + } + ] + } + } + } + } + }, + { + "i": "6415aa25-3a64-44c2-a9fd-f02f18623557", + "x": 0, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "PUE by Year", + "description": "Not every provider publishes PUE for every region. If this tile shows no rows, no PUE has been reported for the selected region.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + }, + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"pue\" FROM \"dataset\" WHERE \"pue\" IS NOT NULL ORDER BY \"year\"" + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "yearLabel", + "type": "nominal", + "title": "Year" + }, + "y": { + "field": "pue", + "type": "quantitative", + "title": "PUE" + } + }, + "markLines": [ + { + "value": 1.2, + "label": "1.2", + "color": "#94A3B8" + } + ], + "style": { + "cartesianSmooth": true, + "cartesianPointRadius": 5, + "showLabels": true, + "colors": [ + "#64748B" + ], + "cartesianYAxisMin": 1 + } + } + } + } + }, + { + "i": "6d9e6219-a862-4a06-a554-27852a06ca64", + "x": 2, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Grid Carbon Intensity by Year", + "description": "", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + }, + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\" FROM \"dataset\" WHERE \"gridCarbonIntensityConsumptionAnnual\" IS NOT NULL ORDER BY \"year\"" + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "yearLabel", + "type": "nominal", + "title": "Year" + }, + "y": { + "field": "gridCi", + "type": "quantitative", + "title": "gCO₂eq/kWh" + } + }, + "style": { + "showLabels": true, + "cartesianBarBorderRadius": 6, + "cartesianShowHorizontalGridLines": false, + "cartesianColorRules": [ + { + "lt": 100, + "color": "#16A34A" + }, + { + "lt": 400, + "color": "#F59E0B" + }, + { + "gte": 400, + "color": "#DC2626" + } + ] + } + } + } + } + }, + { + "i": "d10d12eb-c07e-4498-9f41-8c9560c41727", + "x": 0, + "y": 5, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Region Estimates", + "description": "GSF’s own projections for the current year, trended from previous years’ reported data. These are estimates, not measurements.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionEstimates]}}", + "name": "regionEstimates", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "region": { + "variable": "{{variables.[Cloud Region]}}", + "workspace": "{{workspaceId}}", + "scope": "{{scopes.[Cloud Regions]}}" + } + }, + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"pue\", \"wue\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\", ROUND(\"gridCarbonIntensityMarginalAnnual\", 0) AS \"marginalCi\", ROUND(\"providerCfeHourly\" * 100, 0) AS \"cfePct\" FROM \"dataset\" ORDER BY \"year\" DESC" + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "yearLabel", + "title": "Year", + "renderer": { + "type": "text" + } + }, + { + "field": "gridCi", + "title": "Grid CI (consumption)", + "renderer": { + "type": "number", + "decimals": 0, + "thresholds": [ + { + "to": 100, + "color": "#16A34A" + }, + { + "to": 400, + "color": "#F59E0B" + }, + { + "to": 100000, + "color": "#DC2626" + } + ] + }, + "align": "right" + }, + { + "field": "marginalCi", + "title": "Grid CI (marginal)", + "renderer": { + "type": "number", + "decimals": 0 + }, + "align": "right" + }, + { + "field": "pue", + "title": "PUE", + "renderer": { + "type": "number", + "decimals": 2, + "thresholds": [ + { + "to": 1.15, + "color": "#16A34A" + }, + { + "to": 1.3, + "color": "#F59E0B" + }, + { + "to": 100, + "color": "#DC2626" + } + ] + }, + "align": "right" + }, + { + "field": "wue", + "title": "WUE (L/kWh)", + "renderer": { + "type": "number", + "decimals": 2, + "thresholds": [ + { + "to": 0.5, + "color": "#16A34A" + }, + { + "to": 1.0, + "color": "#F59E0B" + }, + { + "to": 100, + "color": "#DC2626" + } + ] + }, + "align": "right" + }, + { + "field": "cfePct", + "title": "Hourly CFE", + "renderer": { + "type": "progress", + "max": 100 + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableAltRowColor": "rgba(148,163,184,0.08)" + } + } + } + } + }, + { + "i": "8f443c59-5be5-4801-97b1-7db589c85baa", + "x": 0, + "y": 8, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Region Details", + "description": "", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "variables": [ + "{{variables.[Cloud Region]}}" + ], + "scope": { + "scope": "{{scopes.[Cloud Regions]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Cloud Region]}}" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "provider", + "title": "Provider", + "renderer": { + "type": "badge", + "colors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + } + } + }, + { + "field": "region", + "title": "Region", + "renderer": { + "type": "text" + } + }, + { + "field": "location", + "title": "Location", + "renderer": { + "type": "text" + } + }, + { + "field": "cfeRegion", + "title": "CFE region", + "renderer": { + "type": "text" + } + }, + { + "field": "emZoneId", + "title": "Electricity Maps zone", + "renderer": { + "type": "text" + } + }, + { + "field": "wtRegionId", + "title": "WattTime region", + "renderer": { + "type": "text" + } + }, + { + "field": "latitude", + "title": "Latitude", + "renderer": { + "type": "text" + } + }, + { + "field": "longitude", + "title": "Longitude", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableTranspose": true, + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "b7d2e4a1-8c3f-4e59-a6b0-2d9f1c5e7384", + "x": 0, + "y": 11, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/text", + "title": "", + "description": "", + "visualisation": { + "config": { + "content": "**How these figures are produced**\n\nReal Time Cloud is reference data published by the Green Software Foundation (GSF), not live telemetry. Figures are read live from GSF and updated about once a year.\n\n- **Reported values** are annual figures that cloud providers disclose (such as PUE, WUE and carbon-free energy) together with grid carbon intensity from third parties (Electricity Maps and WattTime). Blank cells mean the provider has not published a value, so some regions have gaps.\n- **Estimates** are GSF’s own projections for the current year, trended from previous years’ reported data. They are not measurements.\n- Azure and Oracle figures follow provider fiscal years, and Azure values are set per continent rather than per region.", + "fontSize": 20, + "align": "left", + "autoSize": false + } + } + } + } + ] + } +} diff --git a/plugins/RealTimeCloud/v1/defaultContent/efficiency.dash.json b/plugins/RealTimeCloud/v1/defaultContent/efficiency.dash.json new file mode 100644 index 00000000..8a63fc58 --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/efficiency.dash.json @@ -0,0 +1,505 @@ +{ + "name": "Efficiency", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "391d4afd-2a95-4785-8e0f-5612a5be2e48", + "x": 0, + "y": 0, + "w": 4, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Data centre efficiency", + "description": "PUE (power usage effectiveness, 1.0 is ideal) and WUE (litres of water per kWh) across regions that disclose them, latest disclosed year", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT ROUND(AVG(\"pue\"), 2) AS \"avgPue\", ROUND(MIN(\"pue\"), 2) AS \"bestPue\", ROUND(AVG(\"wue\"), 2) AS \"avgWue\", ROUND(MIN(\"wue\"), 2) AS \"bestWue\" FROM \"dataset\" WHERE \"isLatest\" = 1" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "avgPue", + "type": "quantitative", + "title": "Avg PUE" + }, + { + "field": "bestPue", + "type": "quantitative", + "title": "Best PUE" + }, + { + "field": "avgWue", + "type": "quantitative", + "title": "Avg WUE (L/kWh)" + }, + { + "field": "bestWue", + "type": "quantitative", + "title": "Best WUE (L/kWh)" + } + ] + }, + "style": { + "scalarColumns": 4 + } + } + } + } + }, + { + "i": "a808cf91-59ca-4f75-a8e0-8f341ed10fae", + "x": 0, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Avg PUE by provider", + "description": "Mean PUE of regions that disclose it, latest disclosed year. Lower is better.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"provider\", ROUND(AVG(\"pue\"), 3) AS \"avgPue\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"pue\" IS NOT NULL GROUP BY \"provider\" ORDER BY \"avgPue\"" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "provider", + "type": "nominal", + "title": "Provider" + }, + "y": { + "field": "avgPue", + "type": "quantitative", + "title": "Avg PUE" + } + }, + "markLines": [ + { + "value": 1.2, + "label": "1.2", + "color": "#94A3B8" + } + ], + "style": { + "showLabels": true, + "cartesianBarBorderRadius": 6, + "cartesianShowHorizontalGridLines": false, + "cartesianColorRules": [ + { + "label": "Amazon Web Services", + "color": "#8B5CF6" + }, + { + "label": "Google Cloud", + "color": "#38BDF8" + }, + { + "label": "Microsoft Azure", + "color": "#1E3A8A" + } + ], + "cartesianYAxisMin": 1 + } + } + } + } + }, + { + "i": "0e5e4560-7cb2-4663-bea5-956adc8fa451", + "x": 2, + "y": 2, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "10 highest water-use regions", + "description": "WUE in litres of water per kWh, latest disclosed year. Green: 0.5 or less. Amber: up to 1.0. Red: over 1.0. Only AWS publishes regional WUE for its latest year.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\" || ' · ' || CASE \"provider\" WHEN 'Amazon Web Services' THEN 'AWS' WHEN 'Google Cloud' THEN 'GCP' WHEN 'Microsoft Azure' THEN 'Azure' ELSE \"provider\" END AS \"regionLabel\", \"wue\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"wue\" IS NOT NULL ORDER BY \"wue\" DESC LIMIT 10" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "regionLabel", + "type": "nominal", + "title": "Region" + }, + "y": { + "field": "wue", + "type": "quantitative", + "title": "WUE (L/kWh)" + } + }, + "style": { + "cartesianHorizontal": true, + "showLabels": true, + "cartesianBarBorderRadius": 4, + "cartesianShowHorizontalGridLines": false, + "cartesianYAxisMin": 0, + "cartesianColorRules": [ + { + "lte": 0.5, + "color": "#16A34A" + }, + { + "lte": 1.0, + "color": "#F59E0B" + }, + { + "gt": 1.0, + "color": "#DC2626" + } + ] + } + } + } + } + }, + { + "i": "988dcd35-52fc-4812-a439-96d6e18d465b", + "x": 0, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "PUE trend by provider", + "description": "Mean regional PUE per year. Disclosed values, then estimates for years after each provider's latest disclosure.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "datastream-sql", + "dataSourceConfig": { + "version": "2.0", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 3) AS \"avgPue\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"pue\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"pue\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "tables": [ + { + "tableName": "hist", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + }, + { + "tableName": "est", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionEstimates]}}", + "name": "regionEstimates", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + } + ] + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "yearLabel", + "type": "nominal", + "title": "Year" + }, + "y": { + "field": "avgPue", + "type": "quantitative", + "title": "Avg PUE" + }, + "series": { + "field": "provider", + "type": "nominal" + } + }, + "style": { + "cartesianSmooth": true, + "legendPosition": "bottom", + "cartesianPointRadius": 4, + "mappedColors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + }, + "cartesianYAxisMin": 1 + } + } + } + } + }, + { + "i": "bc35fc7d-1cb4-41d4-b8ab-97aa7421f0a4", + "x": 2, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "WUE trend by provider", + "description": "Mean regional WUE (L/kWh) per year. Disclosed values, then estimates for years after each provider's latest disclosure.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "datastream-sql", + "dataSourceConfig": { + "version": "2.0", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 2) AS \"avgWue\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"wue\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"wue\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "tables": [ + { + "tableName": "hist", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + }, + { + "tableName": "est", + "config": { + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionEstimates]}}", + "name": "regionEstimates", + "pluginConfigId": "{{configId}}" + }, + "timeframe": "none" + } + } + ] + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "yearLabel", + "type": "nominal", + "title": "Year" + }, + "y": { + "field": "avgWue", + "type": "quantitative", + "title": "Avg WUE (L/kWh)" + }, + "series": { + "field": "provider", + "type": "nominal" + } + }, + "style": { + "cartesianSmooth": true, + "legendPosition": "bottom", + "cartesianPointRadius": 4, + "mappedColors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + }, + "cartesianYAxisMin": 0 + } + } + } + } + }, + { + "i": "15aa0701-28b5-448e-ae36-2fa3726cfc79", + "x": 0, + "y": 8, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Regions by efficiency", + "description": "PUE: green under 1.15, amber under 1.3, red above. WUE (litres per kWh): green 0.5 or less, amber up to 1.0, red above. Latest disclosed year; regions with no PUE or WUE are left out.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\", \"provider\", \"location\", CAST(\"year\" AS INTEGER) AS \"year\", \"pue\", \"wue\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND (\"pue\" IS NOT NULL OR \"wue\" IS NOT NULL) ORDER BY \"pue\" ASC NULLS LAST" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "region", + "title": "Region", + "renderer": { + "type": "text" + } + }, + { + "field": "provider", + "title": "Provider", + "renderer": { + "type": "badge", + "colors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + } + } + }, + { + "field": "location", + "title": "Location", + "renderer": { + "type": "text" + } + }, + { + "field": "year", + "title": "Year", + "renderer": { + "type": "number", + "decimals": 0 + }, + "align": "right" + }, + { + "field": "pue", + "title": "PUE", + "renderer": { + "type": "number", + "decimals": 2, + "thresholds": [ + { + "to": 1.15, + "color": "#16A34A" + }, + { + "to": 1.3, + "color": "#F59E0B" + }, + { + "to": 100, + "color": "#DC2626" + } + ] + }, + "align": "right" + }, + { + "field": "wue", + "title": "WUE (L/kWh)", + "renderer": { + "type": "bar", + "thresholds": [ + { + "to": 0.5, + "color": "#16A34A" + }, + { + "to": 1.0, + "color": "#F59E0B" + }, + { + "to": 100, + "color": "#DC2626" + } + ] + } + } + ] + }, + "style": { + "richTableSort": { + "field": "pue", + "direction": "asc" + }, + "richTableCellPadding": 6, + "richTableAltRowColor": "rgba(148,163,184,0.08)" + } + } + } + } + } + ] + } +} diff --git a/plugins/RealTimeCloud/v1/defaultContent/manifest.json b/plugins/RealTimeCloud/v1/defaultContent/manifest.json new file mode 100644 index 00000000..1d8b319e --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/manifest.json @@ -0,0 +1,20 @@ +{ + "items": [ + { + "name": "overview", + "type": "dashboard" + }, + { + "name": "carbonIntensity", + "type": "dashboard" + }, + { + "name": "efficiency", + "type": "dashboard" + }, + { + "name": "cloudRegion", + "type": "dashboard" + } + ] +} diff --git a/plugins/RealTimeCloud/v1/defaultContent/overview.dash.json b/plugins/RealTimeCloud/v1/defaultContent/overview.dash.json new file mode 100644 index 00000000..b5af7500 --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/overview.dash.json @@ -0,0 +1,289 @@ +{ + "name": "Overview", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "f0c9ccb9-3ad6-438b-935d-95f2306e30d1", + "x": 0, + "y": 0, + "w": 4, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "At a glance", + "description": "Latest provider-disclosed year for each cloud region (AWS, Google Cloud, Azure)", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT COUNT(DISTINCT \"regionId\") AS \"regions\", ROUND(AVG(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"avgGridCi\", ROUND(AVG(\"pue\"), 2) AS \"avgPue\", ROUND(AVG(\"providerCfeHourly\") * 100, 0) AS \"avgCfe\" FROM \"dataset\" WHERE \"isLatest\" = 1" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "regions", + "type": "quantitative", + "title": "Cloud regions tracked" + }, + { + "field": "avgGridCi", + "type": "quantitative", + "title": "Avg grid carbon intensity (gCO₂eq/kWh)" + }, + { + "field": "avgPue", + "type": "quantitative", + "title": "Avg PUE" + }, + { + "field": "avgCfe", + "type": "quantitative", + "title": "Avg hourly carbon-free energy (%)" + } + ] + }, + "style": { + "scalarColumns": 4 + } + } + } + } + }, + { + "i": "bb6c4180-105c-403c-b89c-5960b2ae9969", + "x": 0, + "y": 2, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Cloud regions by grid carbon intensity", + "description": "Green: under 100 gCO₂eq/kWh. Amber: 100–400. Red: over 400. Grey: no data. Latest disclosed year.", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"region\", \"provider\", \"location\", \"latitude\", \"longitude\", ROUND(\"gridCarbonIntensityConsumptionAnnual\", 0) AS \"gridCi\", CASE WHEN \"gridCarbonIntensityConsumptionAnnual\" IS NULL THEN 'Unknown' WHEN \"gridCarbonIntensityConsumptionAnnual\" < 100 THEN 'Low' WHEN \"gridCarbonIntensityConsumptionAnnual\" < 400 THEN 'Medium' ELSE 'High' END AS \"carbonBand\" FROM \"dataset\" WHERE \"isLatest\" = 1 AND \"latitude\" IS NOT NULL AND \"longitude\" IS NOT NULL" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "geoMap", + "encoding": { + "latitude": { + "field": "latitude", + "type": "quantitative" + }, + "longitude": { + "field": "longitude", + "type": "quantitative" + }, + "label": { + "field": "region", + "type": "nominal" + }, + "status": { + "field": "carbonBand", + "type": "nominal" + }, + "details": [ + { + "field": "provider", + "type": "nominal" + }, + { + "field": "location", + "type": "nominal" + }, + { + "field": "gridCi", + "type": "quantitative" + }, + { + "field": "carbonBand", + "type": "nominal" + } + ] + }, + "style": { + "geoMapBase": "world", + "geoMapStatusMap": { + "Low": "success", + "Medium": "warning", + "High": "error", + "Unknown": "unknown" + }, + "geoMapPointSize": 9, + "geoMapZoomControls": true, + "geoMapWheelZoom": false, + "showLabels": false + } + } + } + } + }, + { + "i": "b5196f4a-f578-48ba-acbd-61d3aa4944f1", + "x": 0, + "y": 6, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Avg grid carbon intensity by provider", + "description": "Mean of regional grid carbon intensity (consumption, annual), gCO₂eq/kWh, latest disclosed year", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"provider\", ROUND(AVG(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"avgGridCi\" FROM \"dataset\" WHERE \"isLatest\" = 1 GROUP BY \"provider\" ORDER BY \"avgGridCi\"" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "provider", + "type": "nominal", + "title": "Provider" + }, + "y": { + "field": "avgGridCi", + "type": "quantitative", + "title": "Avg grid carbon intensity (gCO₂eq/kWh)" + } + }, + "style": { + "showLabels": true, + "cartesianBarBorderRadius": 6, + "cartesianShowHorizontalGridLines": false, + "cartesianColorRules": [ + { + "label": "Amazon Web Services", + "color": "#8B5CF6" + }, + { + "label": "Google Cloud", + "color": "#38BDF8" + }, + { + "label": "Microsoft Azure", + "color": "#1E3A8A" + } + ] + } + } + } + } + }, + { + "i": "c07f525d-ff7a-4e01-a23f-357750e7940c", + "x": 2, + "y": 6, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Regions by provider", + "description": "Number of cloud regions with disclosed data", + "timeframe": "none", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[regionMetadata]}}", + "name": "regionMetadata", + "pluginConfigId": "{{configId}}", + "sql": "SELECT \"provider\", COUNT(DISTINCT \"regionId\") AS \"regions\" FROM \"dataset\" WHERE \"isLatest\" = 1 GROUP BY \"provider\" ORDER BY \"regions\" DESC" + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "provider", + "type": "nominal" + }, + "value": { + "field": "regions", + "type": "quantitative" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieBorderRadius": 6, + "piePadAngle": 2, + "mappedColors": { + "Amazon Web Services": "#8B5CF6", + "Google Cloud": "#38BDF8", + "Microsoft Azure": "#1E3A8A" + } + } + } + } + } + }, + { + "i": "549abda6-fc76-4875-aafe-d3cdfeee5134", + "x": 0, + "y": 9, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/text", + "title": "", + "description": "", + "visualisation": { + "config": { + "content": "**How these figures are produced**\n\nReal Time Cloud is reference data published by the Green Software Foundation (GSF), not live telemetry. Figures are read live from GSF and updated about once a year.\n\n- **Reported values** are annual figures that cloud providers disclose (such as PUE, WUE and carbon-free energy) together with grid carbon intensity from third parties (Electricity Maps and WattTime). Blank cells mean the provider has not published a value, so some regions have gaps.\n- **Estimates** are GSF’s own projections for the current year, trended from previous years’ reported data. They are not measurements.\n- Azure and Oracle figures follow provider fiscal years, and Azure values are set per continent rather than per region.", + "fontSize": 20, + "align": "left", + "autoSize": false + } + } + } + } + ] + } +} diff --git a/plugins/RealTimeCloud/v1/defaultContent/scopes.json b/plugins/RealTimeCloud/v1/defaultContent/scopes.json new file mode 100644 index 00000000..618105b0 --- /dev/null +++ b/plugins/RealTimeCloud/v1/defaultContent/scopes.json @@ -0,0 +1,19 @@ +[ + { + "name": "Cloud Regions", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Cloud Region" + ] + } + }, + "variable": { + "name": "Cloud Region", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + } +] diff --git a/plugins/RealTimeCloud/v1/docs/README.md b/plugins/RealTimeCloud/v1/docs/README.md new file mode 100644 index 00000000..1eb831ac --- /dev/null +++ b/plugins/RealTimeCloud/v1/docs/README.md @@ -0,0 +1,52 @@ +Explore the sustainability metadata of AWS, Azure, Google Cloud and Oracle Cloud Infrastructure regions in SquaredUp — power and water usage effectiveness, carbon-free energy and grid carbon intensity — using the data published by the [Green Software Foundation (GSF) Real Time Cloud project](https://github.com/Green-Software-Foundation/real-time-cloud). The data belongs to GSF and is fetched live from GSF's repository, not stored or redistributed by this plugin. + +> ⚠️ This is reference data published once a year by the cloud providers, not live telemetry. It does not report your own workloads' emissions. + +## Setup + +No account, API key or credentials are needed — the data is read from public CSV files on GitHub. + +1. Add the **Real Time Cloud** data source in SquaredUp. +2. Save the data source. + +## Configuration fields + +There are no configuration fields. The data is always read from the `main` branch of the Real Time Cloud repository. + +On save, the plugin fetches the region metadata file; a failure means the Green Software Foundation data is unreachable. + +## What this plugin monitors + +- **Energy efficiency** — power usage effectiveness (PUE) and water usage effectiveness (WUE) per region. +- **Carbon-free energy** — each provider's hourly and annual carbon-free energy share. +- **Carbon intensity** — provider market-based and grid consumption, production and marginal carbon intensity (gCO₂eq/kWh). +- **Energy and water totals** — total water input where GSF publishes it. GSF's total ICT energy and renewable energy columns (required for EU Energy Efficiency Directive reporting) are currently empty, so the plugin hides them. + +The out-of-the-box dashboards include an **Overview** (headline figures and a world map of regions by grid carbon intensity), **Carbon Intensity** (cleanest and highest-carbon regions, trends by provider), **Efficiency** (PUE and WUE by provider and region) and a perspective for each **Cloud Region**. + +## Data streams + +- **Region Metadata** — provider-disclosed annual metrics, one row per region per year; account-wide, or filtered to selected regions. +- **Region Estimates** — GSF's own estimates for the current year, trended from earlier disclosed data and published in GSF's estimate file. They are estimates, not measurements, and the years covered follow GSF's latest release. Account-wide, or filtered to selected regions. + +## What gets indexed + +| Object type | API source | Represents | +| ---------------- | -------------------------------------------------------- | ------------------------------------------------------- | +| **Cloud Region** | `Cloud_Region_Metadata.csv` in the Real Time Cloud repo. | A cloud provider region, such as AWS `eu-west-1`. | + +## Known limitations + +- **Annual data** — values are yearly averages, so the streams have no timeframe selector. +- **Gaps** — providers do not disclose every metric for every region and year; missing values are shown empty. +- **Disclosure lag** — providers publish about six months after year end, so the latest reported year is usually the previous one. Estimates cover the current year. +- **Providers covered** — AWS, Microsoft Azure, Google Cloud and Oracle Cloud Infrastructure. Oracle appears once GSF's published data includes it. +- **Provider granularity** — Azure PUE and WUE are set per continent rather than per region, and Google PUE is per datacenter mapped to a region. Oracle has no PUE or WUE for recent years. +- **Reporting periods** — Azure figures follow a July–June fiscal year and Oracle figures a June–May fiscal year, so they are not directly comparable with calendar-year values. +- **Third-party grid data** — grid carbon intensity and the Electricity Maps and WattTime zone IDs are third-party data carried forward by GSF. +- **Latest-year dashboards** — Overview, Carbon Intensity and Efficiency show each region's latest reported year, so averages can mix years where a region has not reported recently. +- **Read-only** — the plugin only reads public files. + +## Attribution + +Data is published by the [Green Software Foundation](https://greensoftware.foundation) in the [Real Time Cloud](https://github.com/Green-Software-Foundation/real-time-cloud) project. Grid carbon intensity includes data from Electricity Maps and WattTime. This plugin is not affiliated with or endorsed by the Green Software Foundation. diff --git a/plugins/RealTimeCloud/v1/icon.svg b/plugins/RealTimeCloud/v1/icon.svg new file mode 100644 index 00000000..9bcc3335 --- /dev/null +++ b/plugins/RealTimeCloud/v1/icon.svg @@ -0,0 +1 @@ + diff --git a/plugins/RealTimeCloud/v1/indexDefinitions/default.json b/plugins/RealTimeCloud/v1/indexDefinitions/default.json new file mode 100644 index 00000000..1dcf3027 --- /dev/null +++ b/plugins/RealTimeCloud/v1/indexDefinitions/default.json @@ -0,0 +1,24 @@ +{ + "steps": [ + { + "name": "regions", + "dataStream": { "name": "regions" }, + "timeframe": "none", + "objectMapping": { + "id": "regionId", + "name": "name", + "type": { "value": "Cloud Region" }, + "properties": [ + "provider", + "region", + "location", + "cfeRegion", + "emZoneId", + "wtRegionId", + "latitude", + "longitude" + ] + } + } + ] +} diff --git a/plugins/RealTimeCloud/v1/metadata.json b/plugins/RealTimeCloud/v1/metadata.json new file mode 100644 index 00000000..d8aff396 --- /dev/null +++ b/plugins/RealTimeCloud/v1/metadata.json @@ -0,0 +1,51 @@ +{ + "name": "real-time-cloud", + "displayName": "Real Time Cloud", + "version": "1.0.0", + "author": { + "name": "@masokisi", + "type": "community" + }, + "description": "Cloud region sustainability metadata for AWS, Azure, Google Cloud and Oracle Cloud Infrastructure — PUE, WUE, carbon-free energy and grid carbon intensity — from the Green Software Foundation Real Time Cloud project.", + "category": "Analytics", + "type": "cloud", + "schemaVersion": "2.1", + "importNotSupported": false, + "restrictedToPlatforms": [], + "keywords": [ + "sustainability", + "carbon", + "green software", + "GSF", + "PUE", + "WUE", + "AWS", + "Azure", + "GCP", + "Oracle", + "OCI" + ], + "objectTypes": ["Cloud Region"], + "links": [ + { + "category": "documentation", + "url": "https://github.com/squaredup/plugins/blob/main/plugins/RealTimeCloud/v1/docs/README.md", + "label": "Help adding this plugin" + }, + { + "category": "source", + "url": "https://github.com/squaredup/plugins/tree/main/plugins/RealTimeCloud/v1", + "label": "Repository" + } + ], + "base": { + "plugin": "WebAPI", + "majorVersion": "1", + "config": { + "baseUrl": "https://raw.githubusercontent.com/Green-Software-Foundation/real-time-cloud/main", + "authMode": "none", + "headers": [], + "queryArgs": [] + } + } +} diff --git a/plugins/RealTimeCloud/v1/ui.json b/plugins/RealTimeCloud/v1/ui.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/plugins/RealTimeCloud/v1/ui.json @@ -0,0 +1 @@ +[] From 2b4676434bd00b94a2a31c007424f84402d5d193 Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Mon, 26 Oct 2026 13:12:18 +0000 Subject: [PATCH 2/7] Validate CSV structure in Real Time Cloud stream scripts Reject empty responses, unterminated quoted fields and missing cloud-provider, cloud-region or year headers with a clear error. Co-Authored-By: Claude Sonnet 5.5 --- .../v1/dataStreams/scripts/regionEstimates.js | 7 +++++++ .../RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js | 7 +++++++ plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js index 3ed090be..9332b6f2 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js @@ -28,7 +28,14 @@ const parseCsv = (text) => { row.push(field); rows.push(row); } + if (quoted) throw new Error("Invalid CSV: unterminated quoted field"); + if (!rows.length) throw new Error("Invalid CSV: empty response"); const header = rows.shift().map((h) => h.trim()); + const missing = ["cloud-provider", "cloud-region", "year"].filter( + (name) => !header.includes(name), + ); + if (missing.length) + throw new Error(`Invalid CSV: missing columns ${missing.join(", ")}`); return rows.map((r) => Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), ); diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js index e51dbdd2..0599673d 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js @@ -28,7 +28,14 @@ const parseCsv = (text) => { row.push(field); rows.push(row); } + if (quoted) throw new Error("Invalid CSV: unterminated quoted field"); + if (!rows.length) throw new Error("Invalid CSV: empty response"); const header = rows.shift().map((h) => h.trim()); + const missing = ["cloud-provider", "cloud-region", "year"].filter( + (name) => !header.includes(name), + ); + if (missing.length) + throw new Error(`Invalid CSV: missing columns ${missing.join(", ")}`); return rows.map((r) => Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), ); diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js index 24df0de7..ea5a337d 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js @@ -28,7 +28,14 @@ const parseCsv = (text) => { row.push(field); rows.push(row); } + if (quoted) throw new Error("Invalid CSV: unterminated quoted field"); + if (!rows.length) throw new Error("Invalid CSV: empty response"); const header = rows.shift().map((h) => h.trim()); + const missing = ["cloud-provider", "cloud-region", "year"].filter( + (name) => !header.includes(name), + ); + if (missing.length) + throw new Error(`Invalid CSV: missing columns ${missing.join(", ")}`); return rows.map((r) => Object.fromEntries(header.map((h, i) => [h, (r[i] ?? "").trim()])), ); From 2086989b43eee78881a3b6f93e7da5cb24d8c6d5 Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Tue, 27 Oct 2026 10:03:00 +0000 Subject: [PATCH 3/7] Treat omitted optional CSV columns as null in Real Time Cloud scripts Co-Authored-By: Claude Sonnet 5.5 --- .../RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js | 5 +++-- .../RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js | 5 +++-- plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js index 9332b6f2..ee5c6175 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js @@ -41,12 +41,13 @@ const parseCsv = (text) => { ); }; const num = (v) => - v === "" || v.toUpperCase() === "NA" + v == null || v === "" || v.toUpperCase() === "NA" ? null : Number.isFinite(Number(v)) ? Number(v) : null; -const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const str = (v) => + v == null || v === "" || v.toUpperCase() === "NA" ? null : v; const geo = (v) => { const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); return { latitude: lat ?? null, longitude: lon ?? null }; diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js index 0599673d..62826d2d 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js @@ -41,12 +41,13 @@ const parseCsv = (text) => { ); }; const num = (v) => - v === "" || v.toUpperCase() === "NA" + v == null || v === "" || v.toUpperCase() === "NA" ? null : Number.isFinite(Number(v)) ? Number(v) : null; -const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const str = (v) => + v == null || v === "" || v.toUpperCase() === "NA" ? null : v; const geo = (v) => { const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); return { latitude: lat ?? null, longitude: lon ?? null }; diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js index ea5a337d..fc62f231 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js @@ -41,12 +41,13 @@ const parseCsv = (text) => { ); }; const num = (v) => - v === "" || v.toUpperCase() === "NA" + v == null || v === "" || v.toUpperCase() === "NA" ? null : Number.isFinite(Number(v)) ? Number(v) : null; -const str = (v) => (v === "" || v.toUpperCase() === "NA" ? null : v); +const str = (v) => + v == null || v === "" || v.toUpperCase() === "NA" ? null : v; const geo = (v) => { const [lat, lon] = (v || "").split(",").map((s) => num(s.trim())); return { latitude: lat ?? null, longitude: lon ?? null }; From 15c64942a6791dd997e37422ab8b74ecab0d508a Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Tue, 27 Oct 2026 10:12:21 +0000 Subject: [PATCH 4/7] Filter null carbon values before grouping in carbon trend Co-Authored-By: Claude Sonnet 5.5 --- .../RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json index dbcc3110..285567c9 100644 --- a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json +++ b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json @@ -213,7 +213,7 @@ "id": "datastream-sql", "dataSourceConfig": { "version": "2.0", - "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensityConsumptionAnnual\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensityConsumptionAnnual\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", "tables": [ { "tableName": "hist", From e86f2c14db03ca4900e4962bd736d1623153a02b Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Tue, 27 Oct 2026 10:38:15 +0000 Subject: [PATCH 5/7] Remove Oracle from plugin description until its data is published Co-Authored-By: Claude Sonnet 5.5 --- plugins/RealTimeCloud/v1/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/RealTimeCloud/v1/metadata.json b/plugins/RealTimeCloud/v1/metadata.json index d8aff396..b3fbfca2 100644 --- a/plugins/RealTimeCloud/v1/metadata.json +++ b/plugins/RealTimeCloud/v1/metadata.json @@ -6,7 +6,7 @@ "name": "@masokisi", "type": "community" }, - "description": "Cloud region sustainability metadata for AWS, Azure, Google Cloud and Oracle Cloud Infrastructure — PUE, WUE, carbon-free energy and grid carbon intensity — from the Green Software Foundation Real Time Cloud project.", + "description": "Cloud region sustainability metadata — PUE, WUE, carbon-free energy and grid carbon intensity — from the Green Software Foundation Real Time Cloud project.", "category": "Analytics", "type": "cloud", "schemaVersion": "2.1", From b24661b1edaf528e9551998f87527829c9f766d6 Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Tue, 27 Oct 2026 10:50:33 +0000 Subject: [PATCH 6/7] Use parsed body in CSV scripts and read populated estimate carbon column Co-Authored-By: Claude Sonnet 5.5 --- plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js | 2 +- plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js | 2 +- plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js | 2 +- .../RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js index ee5c6175..08293800 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionEstimates.js @@ -58,7 +58,7 @@ const unwrap = (v) => (Array.isArray(v) ? v[0] : v); const selected = (context.config && context.config.region) || []; const ids = new Set(selected.map((o) => unwrap(o.rawId)).filter(Boolean)); -result = parseCsv(response.body) +result = parseCsv(typeof data === "string" ? data : response.body) .filter((r) => r["cloud-provider"] && r["cloud-region"]) .filter( (r) => diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js index 62826d2d..c5c60d91 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regionMetadata.js @@ -58,7 +58,7 @@ const unwrap = (v) => (Array.isArray(v) ? v[0] : v); const selected = (context.config && context.config.region) || []; const ids = new Set(selected.map((o) => unwrap(o.rawId)).filter(Boolean)); -const rows = parseCsv(response.body).filter( +const rows = parseCsv(typeof data === "string" ? data : response.body).filter( (r) => r["cloud-provider"] && r["cloud-region"], ); const latestYear = {}; diff --git a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js index fc62f231..254d6b89 100644 --- a/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js +++ b/plugins/RealTimeCloud/v1/dataStreams/scripts/regions.js @@ -54,7 +54,7 @@ const geo = (v) => { }; const seen = new Set(); -result = parseCsv(response.body) +result = parseCsv(typeof data === "string" ? data : response.body) .filter((r) => r["cloud-provider"] && r["cloud-region"]) .sort((a, b) => Number(b.year) - Number(a.year)) .flatMap((r) => { diff --git a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json index 285567c9..20cee9b6 100644 --- a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json +++ b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json @@ -213,7 +213,7 @@ "id": "datastream-sql", "dataSourceConfig": { "version": "2.0", - "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensityConsumptionAnnual\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensity\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", "tables": [ { "tableName": "hist", From 048d4e7f41a212c768419ea298bfe65e0313d5c5 Mon Sep 17 00:00:00 2001 From: Kevin Hood Date: Tue, 27 Oct 2026 11:00:26 +0000 Subject: [PATCH 7/7] Restrict carbon trend tile to disclosed average data Estimate rows carry forward a different (marginal) measure, so they are not comparable with the disclosed average series. Co-Authored-By: Claude Sonnet 5.5 --- .../defaultContent/carbonIntensity.dash.json | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json index 20cee9b6..bf85ce4c 100644 --- a/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json +++ b/plugins/RealTimeCloud/v1/defaultContent/carbonIntensity.dash.json @@ -204,7 +204,7 @@ "config": { "_type": "tile/data-stream", "title": "Grid carbon intensity trend by provider", - "description": "Mean regional grid carbon intensity per year. Disclosed values, then estimates for years after each provider's latest disclosure.", + "description": "Mean regional grid carbon intensity per year, from values disclosed by each provider. Years without a disclosure are not shown.", "timeframe": "none", "activePluginConfigIds": [ "{{configId}}" @@ -213,7 +213,7 @@ "id": "datastream-sql", "dataSourceConfig": { "version": "2.0", - "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"v\"), 0) AS \"avgGridCi\" FROM (SELECT \"h\".\"year\", \"h\".\"provider\", \"h\".\"gridCarbonIntensityConsumptionAnnual\" AS \"v\" FROM \"hist\" \"h\" UNION ALL SELECT \"e\".\"year\", \"e\".\"provider\", \"e\".\"gridCarbonIntensity\" FROM \"est\" \"e\" WHERE \"e\".\"year\" > (SELECT MAX(\"h2\".\"year\") FROM \"hist\" \"h2\" WHERE \"h2\".\"provider\" = \"e\".\"provider\")) \"u\" WHERE \"v\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", + "sql": "SELECT CAST(CAST(\"year\" AS INTEGER) AS VARCHAR) AS \"yearLabel\", \"provider\", ROUND(AVG(\"gridCarbonIntensityConsumptionAnnual\"), 0) AS \"avgGridCi\" FROM \"hist\" WHERE \"gridCarbonIntensityConsumptionAnnual\" IS NOT NULL GROUP BY \"year\", \"provider\" ORDER BY \"year\", \"provider\"", "tables": [ { "tableName": "hist", @@ -228,20 +228,6 @@ }, "timeframe": "none" } - }, - { - "tableName": "est", - "config": { - "activePluginConfigIds": [ - "{{configId}}" - ], - "dataStream": { - "id": "{{dataStreams.[regionEstimates]}}", - "name": "regionEstimates", - "pluginConfigId": "{{configId}}" - }, - "timeframe": "none" - } } ] }