thegreenwebfoundation / co2.js

An npm module for accessing the green web API, and estimating the carbon emissions from using digital services
Other
399 stars 51 forks source link

Consider exporting SustainableWebDesign (and 1byte) classes #195

Open mgriffin-scottlogic opened 7 months ago

mgriffin-scottlogic commented 7 months ago

I've been attempting to use CO2.js in a typescript project where I wanted to access the separate components of the energy estimation. I tried to use the SustainableWebDesign class but realised that it's not exported so I could not access it directly. There is somewhat of a workaround in that the CO2 class will create an instance of the class as its publicly available method property but it's not ideal.

Would you consider officially exporting these classes so that they can be used directly? I know the energy calculation is only a small piece of code to duplicate but it would be nice to link to it directly and be able to add any updates.

mrchrisadams commented 7 months ago

Hi @mgriffin-scottlogic,

Can I check I understand what you mean?

So, instead of doing this:

import { co2 } from '@tgwf/co2'

// Use the default Sustainable Web Design model
const swd = new co2()

// access some property, maybe an energy constant
swd.model.someEnergyConstant

You'd like to do something a bit like this instead?

import { SustainableWebDesign } from '@tgwf/co2/models'

const myVal = SustainableWebDesign.someEnergyConstant

I'll check with Fershad has he was on the last SWD working group call, and knows a bit more than I do.

mgriffin-scottlogic commented 7 months ago

Roughly yeah, the code I tried to write was:

import SustainableWebDesign from '@tgwf/co2/sustainable-web-design'

const swd = new SustainableWebDesign({})
const energy = swd.energyPerByteByComponent(dataTransferredBytes)

Also since the @types/tgwf__co2 only defines the return type of this method as object, I had to do the following to be able to access the components:

const energy = swd.energyPerByteByComponent(dataTransferredBytes) as Record<string, number>
const networkEnergy = energy['networkEnergy']

Ideally it would return a type/interface like:

interface EnergyPerByte {
  consumerDeviceEnergy: number
  networkEnergy: number
  productionEnergy: number
  dataCenterEnergy: number
}

So that I could access it directly:

const networkEnergy = swd.energyPerByteByComponent(dataTransferredBytes).networkEnergy
fershad commented 5 months ago

@mgriffin-scottlogic I've flagged this as something for the next release. Those energy functions you reference are not actually used in the SWD calculations within CO2.js and I can't comment on why they were originally there. However, exposing them wouldn't be too much to do - though we would need tests written for them which are currently missing.

mgriffin-scottlogic commented 5 months ago

Ah thanks, though I thought that energyPerByteByComponent() was used as part of the calculation? It seems to be used in perByte(), energyPerByte() and energyPerVisitByComponent() in sustainable-web-design.js. These are eventually used as part of the CO2 class and there is a test on its behaviour in sustainable-web-design.test.js

fershad commented 5 months ago

Truth, they are πŸ˜„

fershad commented 4 months ago

One way we could achieve this without having to significantly rearchitect the CO2.js API (which we do want to do eventually, as described in #206) would be to include the models inside of the CO2 class, which is then exported in the library.

class CO2 {
  // ... other code here

  SustainableWebDesignV3() {
    return new SustainableWebDesignV3();
  }

  SustainableWebDesignV4() {
    return new SustainableWebDesignV4();
  }

  OneByte() {
    return new OneByte();
  }
}

export { CO2 };
export default CO2;

This would then allow developers to access any function declared inside of the models in this way

import {co2} from "@tgwf/co2";
let swdmv4 =  new co2().SustainableWebDesignV4();

// Access the Sustainable Web Design Model directly.
const operationalEnergy = swdmv4.operationalEnergyPerSegment(1000);
console.log(operationalEnergy);

// Access the Sustainable Web Design Model via CO2.js API (perByte/perVisit functions)
const emissions = new co2();
const estimate = emissions.perByte(1000)
fershad commented 4 months ago

I will aim to implement this as a patch release for CO2.js v0.16.x

benjaminrancourt commented 2 months ago

If possible, it may be worth exporting other variables used in the tool as well, as these can be used to see if assumptions have changed between two runs of the tool (such as a data update from HTTP archives) and this could explain why a page that hasn't changed has, overnight, a different rating.

Personally, I report some of this data for the sake of transparency when presenting the tool's results to external people. Currently these values ​​are hardcoded. πŸ‘‡

Image

fershad commented 2 months ago

Hi @benjaminrancourt. Would the perByteTrace and perVisitTrace functions of the Sustainable Web Design Model be helpful for that? Or are they missing something that you think should be exposed?

https://developers.thegreenwebfoundation.org/co2js/methods/#perbytetrace-sustainable-web-design-model-only

https://developers.thegreenwebfoundation.org/co2js/methods/#pervisittrace-sustainable-web-design-only

benjaminrancourt commented 2 months ago

Hi @benjaminrancourt. Would the perByteTrace and perVisitTrace functions of the Sustainable Web Design Model be helpful for that? Or are they missing something that you think should be exposed?

https://developers.thegreenwebfoundation.org/co2js/methods/#perbytetrace-sustainable-web-design-model-only

https://developers.thegreenwebfoundation.org/co2js/methods/#pervisittrace-sustainable-web-design-only

Unfortunately no, I actually use the perByteTrace function which provides about the emissions of CO2e, grid intensity and green hosting factor, but I would like to access the Sustainable Web Design constants and ratings from https://github.com/thegreenwebfoundation/co2.js/blob/main/src/constants/index.js.

My goal is to be as transparent as possible, like Hey, if you want to reproduce these results, here are all the assumptions that has been made. And to also be future-proof as well, in case the ratings or other assumptions are updated, so I don't have to worry about keeping a copy of these variables myself.

I actually store a JSON file with the results from CO2.js, so I don't need to retest a page that has already been tested and I can also track the progress of emissions of some web pages that I monitor (like the pages from my website).

Another example, to help my clients understand the ratings, I automatically generate the table from the previous post using code. In fact, since the values are hardcoded, if I want to update them to v4, I have to manually copy them from the SWD or CO2.js. It may be helpful to simply update a usage of SWDMV3_RATINGS to SWDMV4_RATINGS.

{
        "co2": {
          "dataCenterOperationalCO2e": 0.0003079193172,
          "networkOperationalCO2e": 0.0009535696819999999,
          "consumerDeviceOperationalCO2e": 0.00129297584,
          "dataCenterEmbodiedCO2e": 0.000193946376,
          "networkEmbodiedCO2e": 0.00021010857399999998,
          "consumerDeviceEmbodiedCO2e": 0.001309138038,
          "totalEmbodiedCO2e": 0.0017131929879999998,
          "totalOperationalCO2e": 0.0025544648391999996,
          "dataCenterCO2e": 0.0005018656932,
          "networkCO2e": 0.0011636782559999999,
          "consumerDeviceCO2e": 0.0026021138779999996,
          "total": 0.00395973851,
          "rating": "A+"
        },
        "green": true,
        "variables": {
          "description": "Below are the variables used to calculate this CO2 estimate.",
          "bytes": 32717,
          "gridIntensity": {
            "description": "The grid intensity (grams per kilowatt-hour) used to calculate this CO2 estimate.",
            "device": {
              "value": 494
            },
            "dataCenter": {
              "country": "CAN",
              "value": 171.12
            },
            "network": {
              "value": 494
            }
          },
          "greenHostingFactor": 1
        }
      }
fershad commented 2 months ago

@benjaminrancourt so it would be helpful for you to have information about the model used returned in the trace results? Something like this:

{
        "co2": {
          ...
        },
        "green": true,
        "variables": {
          ...
        },
       "model": {
           "name": "Sustainable Web Design Model",
           "version": 3,
           "shorthand": "swdmv3",
           "constants": {
               ... // a list of constants & their values here
           }
      }
benjaminrancourt commented 2 months ago

@fershad Yeah, it would perfect!