diff --git a/content/en/docs/carbondb/overview.md b/content/en/docs/carbondb/overview.md index 49697f2..10f835e 100644 --- a/content/en/docs/carbondb/overview.md +++ b/content/en/docs/carbondb/overview.md @@ -84,7 +84,7 @@ Cronjobs are all placed in the `/cron` directory of GMT and are de-activated by The following cron jobs are used to maintain the data in CarbonDB: -- **carbondb_copy_over_and_remove_duplicates.py**: This cron job copies data from other sources (e.g., `hog_simplified_measurements`, `ci_measurements`) into the `carbondb_data_raw` table. It also backfills missing carbon intensity data. +- **carbondb_copy_over_and_remove_duplicates.py**: This cron job copies data from other sources (e.g., `hog_simplified_measurements`, `ci_measurements`) into the `carbondb_data_raw` table. It also de-duplicates the data and validates that the copied over data is complete. - **carbondb_compress.py**: This cron job compresses the raw data in `carbondb_data_raw` into daily sums. It also normalizes the data by transforming text fields into integers and storing them in separate tables. - **backfill_geo.py**: This cron job will backfill geo information for IPs. They are needed to backfill carbon intensity which works on Geo coordinates. + The cron job only backfills IP data up to 30 days. Then it considers information to be outdate diff --git a/content/en/docs/cluster/accuracy-control.md b/content/en/docs/cluster/accuracy-control.md index 60bedba..16cbbf8 100644 --- a/content/en/docs/cluster/accuracy-control.md +++ b/content/en/docs/cluster/accuracy-control.md @@ -23,7 +23,7 @@ cluster: name: "Measurement control Workload" uri: "https://github.com/green-coding-solutions/measurement-control-workload" filename: "usage_scenario.yml" - branch: "main" + branch: "event-bound" comparison_window: 5 phase: "004_[RUNTIME]" metrics: @@ -39,10 +39,7 @@ cluster: cpu_energy_rapl_msr_component: threshold: 0.01 # 1% type: stddev_rel - cpu_energy_rapl_msr_component: - threshold: 0.01 # 1% - type: stddev_rel - psu_co2_ac_mcp_machine: + psu_carbon_ac_mcp_machine: threshold: 0.01 # 1% type: stddev_rel network_total_cgroup_container: diff --git a/content/en/docs/cluster/cron-jobs.md b/content/en/docs/cluster/cron-jobs.md index 6f96c86..192337b 100644 --- a/content/en/docs/cluster/cron-jobs.md +++ b/content/en/docs/cluster/cron-jobs.md @@ -17,7 +17,7 @@ This page provides examples how we setup the *cron jobs*. Adjust the times and f SHELL=/bin/bash ## Deprecated! We do not recommend to use the cron feature to schedule jobs -#*\/5 * * * * PATH_TO_GMT/venv/bin/python3 PATH_TO_GMT/tools/jobs.py project &>> /var/log/green-metrics-jobs.log +#*\/5 * * * * PATH_TO_GMT/venv/bin/python3 PATH_TO_GMT/cron/jobs.py run &>> /var/log/green-metrics-jobs.log ## We recommend to trigger the email job every 2 minutes ## You can trigger it more often, as it has a locking mechanism. The mechanism is however not fully parallel safe and email processing is not done in a transaction which might lead to race conditions if multiple connections to the DB in parallel try to set the DB lock. diff --git a/content/en/docs/cluster/host-resource-reservations.md b/content/en/docs/cluster/host-resource-reservations.md index cfbd07e..1e3d681 100644 --- a/content/en/docs/cluster/host-resource-reservations.md +++ b/content/en/docs/cluster/host-resource-reservations.md @@ -27,8 +27,8 @@ machine: #### Specifications -- `host_reserved_cpus` **[integer]** (Default 1): Value between 1 and CPU_MAX. CPU_MAX is the amount of available compute threads on the system. -- `host_reserved_memory` **[integer]** (Default 0): Value between 0 and MEMORY_MAX. MEMORY_MAX is the amount of available physical memory on the system. +- `host_reserved_cpus` **[integer]** (Default 1): Value between 1 and CPU_MAX, where CPU_MAX itself is excluded. CPU_MAX is the amount of compute threads Docker reports as available (`docker info --format '{{.NCPU}}'`). At least one thread must be left assignable to containers, so reserving all of them fails. +- `host_reserved_memory` **[integer]** (Default 0): Value between 0 and MEMORY_MAX, where MEMORY_MAX itself is excluded. MEMORY_MAX is the memory Docker reports as available (`docker info --format '{{.MemTotal}}'`), which is not necessarily the physical memory of the host — under Docker Desktop it is the VM's memory. At least one byte must be left assignable to containers, so reserving all of it fails. ## How to choose good values diff --git a/content/en/docs/cluster/installation.md b/content/en/docs/cluster/installation.md index 27198a0..3c7cc6b 100644 --- a/content/en/docs/cluster/installation.md +++ b/content/en/docs/cluster/installation.md @@ -27,17 +27,17 @@ Now you can choose between two modes: ## 1) Systemd Service - Client mode -The `tools/client.py` program is a script that should constantly be running and that periodically checks the database if a new job has been queued for this certain machine. If no job can be retried it sleeps for a certain amount of time set in the configuration file `config.yml`: +The `cron/client.py` program is a script that should constantly be running and that periodically checks the database if a new job has been queued for this certain machine. If no job can be retried it sleeps for a certain amount of time set in the configuration file `config.yml`: ```yml -client: - sleep_time_no_job: 300 - sleep_time_after_job: 300 +cluster: + client: + sleep_time_no_job: 300 ``` -You can also set a time that the script should wait after a job has finished execution to give the system time to cool down. Please use the [calibrate script]({{< relref "/docs/installation/calibration" >}}) to fine tune this value. +There is no fixed cooldown time after a job. Instead the client checks the machine temperature before every job and holds the queue until the machine is back at its baseline: if the machine is hotter than `base_temperature_value` it sleeps 60 seconds and retries, and if it is 10° or more below it warms the machine up before retrying. See [Machine Baseline Checks →]({{< relref "machine-baseline-checks" >}}) for details. Please use the [calibrate script]({{< relref "/docs/installation/calibration" >}}) to fine tune the `base_temperature_value`. -After running a job the client program executes the `tools/cluster/maintenance.py` script that does general house keeping on the machine. This is done in a batch fashion to not run when a benchmark is currently run. +After running a job the client program executes the `maintenance.py` script that does general house keeping on the machine. This is done in a batch fashion to not run when a benchmark is currently run. To make sure that the client is always running you can create a service that will start at boot and keep running. @@ -78,9 +78,11 @@ systemctl --user status green-coding-client # check status You should now see the client reporting it's status on the server. It is important to note that only the client ever talks to the server (polling). The server never tries to contact the client. This is to not create any interrupts while a measurement might be running. -After running a job the client program executes the `tools/cluster/maintenance.py` script that does general house keeping on the machine. This is done in a batch fashion to not run when a benchmark is currently run. +After running a job the client program executes the maintenance script that does general house keeping on the machine. This is done in a batch fashion to not run when a benchmark is currently run. -This script is run as root and thus needs to be in the `/etc/sudoers` file or subdirectories somewhere. We recommend the following: +The script lives in the repository as `tools/cluster/maintenance_original.py`. The installer copies it to `/usr/local/bin/green-metrics-tool/maintenance.py` and makes it owned by root, and that is the path the client actually executes. + +This script is run as root and thus needs to be in the `/etc/sudoers` file or subdirectories somewhere. The installer deliberately does *not* add this entry for you, as it is only needed in cluster mode. We recommend the following: ```bash echo "${USER} ALL=(ALL) NOPASSWD:$(realpath /usr/bin/python3) -I -B -S /usr/local/bin/green-metrics-tool/maintenance.py" | sudo tee /etc/sudoers.d/green-coding-cluster-maintenance @@ -96,13 +98,15 @@ The Green Metrics Tool comes with an implemented queueing and locking mechanism. You can install a cronjob on your system to periodically call: -- `python3 -u PATH_TO_GREEN_METRICS_TOOL/tools/jobs.py project` to measure projects in database queue -- `python3 -u PATH_TO_GREEN_METRICS_TOOL/tools/jobs.py email` to send all emails in the database queue +- `python3 -u PATH_TO_GREEN_METRICS_TOOL/cron/jobs.py run` to measure runs in database queue +- `python3 -u PATH_TO_GREEN_METRICS_TOOL/cron/jobs.py email` to send all emails in the database queue + +Calling `jobs.py run` will print a deprecation warning, as this mode is only intended for CLI testing. Use the *client mode* above for production. The `jobs.py` uses the *Python* faulthandler mechanism and will also report to *STDERR* in case of a segfault. When running the cronjob we advice you to append all the output combined to a log file like so: -`* * * * * python3 -u PATH_TO_GREEN_METRICS_TOOL/tools/jobs.py project &>> /var/log/green-metrics-jobs.log` +`* * * * * python3 -u PATH_TO_GREEN_METRICS_TOOL/cron/jobs.py run &>> /var/log/green-metrics-jobs.log` Be sure to give the `green-metrics-jobs.log` file write access rights. @@ -184,7 +188,7 @@ $ sudo nano /etc/default/grub # Change this line # GRUB_CMDLINE_LINUX_DEFAULT="" -# to +# to # GRUB_CMDLINE_LINUX_DEFAULT="intel_pstate=disable acpi=force" $ sudo update-grub diff --git a/content/en/docs/cluster/machine-baseline-checks.md b/content/en/docs/cluster/machine-baseline-checks.md index 3597e05..fb79863 100644 --- a/content/en/docs/cluster/machine-baseline-checks.md +++ b/content/en/docs/cluster/machine-baseline-checks.md @@ -50,7 +50,7 @@ Also see [Accuracy Control →]({{< relref "accuracy-control" >}}). ## RAPL Power Capping -Verifies that RAPL power limits are at or below the values you have locked on the machine. Ensures a consistent thermal envelope across cluster nodes. +Verifies that the RAPL power limits locked on the machine are **exactly equal** to the values you configure. Ensures a consistent thermal envelope across cluster nodes. ```yaml machine: @@ -60,12 +60,21 @@ machine: psys: 65 # Watts — platform-wide limit (if available) ``` -Each sub-key is independent; omit any you do not want to enforce. Values are compared against the `constraint_0_power_limit_uw` sysfs files under `/sys/devices/virtual/powercap/intel-rapl/`. +Each sub-key is independent; omit any you do not want to enforce. The configured Watt value is converted to microwatts and compared for exact equality against **every** limit the domain exposes — both the long-term (`constraint_0`) and the short-term (`constraint_1`) limit, wherever present. This transitively also catches the two limits disagreeing with each other, which is why we recommend setting both to the same value. + +Domains are discovered under `/sys/devices/virtual/powercap/intel-rapl/`, including nested ones such as `intel-rapl:0:1` for DRAM. Each domain's `name` file classifies it as `package`, `dram` or `psys`, and its `constraint_N_name` files identify which constraint is the long- and which the short-term limit. Domains that expose only a long-term limit — typical for `dram` and `psys` — are checked on that limit alone. To read the current limits on your machine: ```sh -cat /sys/devices/virtual/powercap/intel-rapl/intel-rapl:*/constraint_0_power_limit_uw +for name in /sys/devices/virtual/powercap/intel-rapl/intel-rapl:*/name \ + /sys/devices/virtual/powercap/intel-rapl/intel-rapl:*/*/name; do + domain=$(dirname "$name") + echo "$(basename "$domain") ($(cat "$name")):" + for constraint in "$domain"/constraint_*_name; do + echo " $(cat "$constraint") = $(cat "${constraint%_name}_power_limit_uw") uW" + done +done ``` Also see [Power Saving →]({{< relref "power-saving#power-capping-machines" >}}) for how to make these limits persistent across reboots via a systemd service. @@ -213,12 +222,13 @@ The following three checks need **no** `config.yml` entry at all — they always The [NOP Linux script →]({{< relref "nop-linux" >}}) auto-prepares a machine so that all three of these pass: it disables/masks system and user `systemd` timers, deletes all cron files, and zeroes out the kernel watchdog sysctls, in addition to disabling NTP and removing swap-adjacent packages. Run it once on a fresh cluster machine instead of doing the steps below by hand. -### System-wide Systemd Timers +### Systemd Timers -Runs as root and warns when any active system-wide `systemd` timer is detected. Timers can wake the system and create measurement noise. To inspect active timers: +Warns when any active `systemd` timer is detected. Both scopes are checked: system-wide timers (read via the root helper) and timers in the invoking user's own `systemd` scope. Timers can wake the system and create measurement noise. To inspect active timers: ```sh -systemctl --all list-timers +sudo systemctl --all list-timers # system-wide scope +systemctl --user --all list-timers # user scope ``` ### Cron Files diff --git a/content/en/docs/cluster/nop-linux.md b/content/en/docs/cluster/nop-linux.md index 506b8b5..4f4d605 100644 --- a/content/en/docs/cluster/nop-linux.md +++ b/content/en/docs/cluster/nop-linux.md @@ -16,7 +16,7 @@ NTP. The goal is to keep the system still very close to a production / user setup, but remove invariances from the system without decreasing idle power draw and skewing results. -Please further note that you must execute certain service still periodically. The [client.py](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/cron/client.py) cluster service will periodically run [a cleanup script](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/tools/cluster/cleanup_original.py) +Please further note that you must execute certain service still periodically. The [client.py](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/cron/client.py) cluster service will periodically run [a maintenance script](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/tools/cluster/maintenance_original.py) ```bash #!/bin/bash diff --git a/content/en/docs/cluster/observability.md b/content/en/docs/cluster/observability.md index 53c8e1d..85310b0 100644 --- a/content/en/docs/cluster/observability.md +++ b/content/en/docs/cluster/observability.md @@ -13,7 +13,7 @@ GMT provides two approaches to get insights into the cluster operations. ## Status Page -Under the `/status.html` page of your GMT installation you can find a status page that contains: +Under the `/cluster-status.html` page of your GMT installation you can find a status page that contains: - Currently configured machines in the cluster - Current temperature, installed GMT version and measurement configuration of the machines in the cluster diff --git a/content/en/docs/cluster/security.md b/content/en/docs/cluster/security.md index 9ce5773..01fdc3c 100644 --- a/content/en/docs/cluster/security.md +++ b/content/en/docs/cluster/security.md @@ -166,6 +166,9 @@ GRANT UPDATE ON public.carbondb_sources TO manager; GRANT UPDATE ON public.carbondb_tags TO manager; GRANT UPDATE ON public.carbondb_types TO manager; +-- to insert errors +GRANT USAGE, SELECT ON SEQUENCE jobs_id_seq TO manager; +GRANT SELECT, INSERT ON TABLE jobs TO manager; ``` To complement the configuration you need also have a different `config.yml` file present to read the credentials from. @@ -202,6 +205,35 @@ We recommend NOT to have SMTP credentials on the machines and also connect to th CREATE USER client WITH PASSWORD 'YOUR_PASSWORD'; +GRANT SELECT,INSERT,DELETE ON TABLE jobs TO client; +GRANT USAGE, SELECT ON SEQUENCE jobs_id_seq TO client; +GRANT UPDATE(state) ON TABLE jobs TO client; + +GRANT SELECT,INSERT ON TABLE client_status TO client; +GRANT USAGE, SELECT ON SEQUENCE client_status_id_seq TO client; + +GRANT SELECT(id) ON TABLE network_intercepts TO client; +GRANT INSERT ON TABLE network_intercepts TO client; +GRANT USAGE, SELECT ON SEQUENCE network_intercepts_id_seq TO client; + +GRANT SELECT, INSERT ON TABLE measurement_metrics TO client; +GRANT USAGE, SELECT ON SEQUENCE measurement_metrics_id_seq TO client; + +GRANT SELECT, INSERT ON TABLE measurement_values TO client; +GRANT USAGE, SELECT ON SEQUENCE measurement_values_id_seq TO client; + +GRANT INSERT ON TABLE notes TO client; +GRANT USAGE, SELECT ON SEQUENCE notes_id_seq TO client; + +GRANT SELECT,INSERT ON TABLE phase_stats TO client; +GRANT USAGE, SELECT ON SEQUENCE phase_stats_id_seq TO client; + +GRANT INSERT on cluster_changelog to client; +GRANT SELECT, USAGE on cluster_changelog_id_seq to client; + +GRANT SELECT,INSERT on warnings to client; +GRANT SELECT, USAGE on warnings_id_seq to client; + GRANT SELECT ON TABLE runs TO client; -- only needs a full select if optimizations are run on the measurement machines. Otherwise can be locked down REVOKE ALL PRIVILEGES ON DATABASE "green-coding" FROM client; diff --git a/content/en/docs/contributing/green-metrics-tool-contribution.md b/content/en/docs/contributing/green-metrics-tool-contribution.md index 3d75238..439b87f 100644 --- a/content/en/docs/contributing/green-metrics-tool-contribution.md +++ b/content/en/docs/contributing/green-metrics-tool-contribution.md @@ -64,7 +64,7 @@ A metric provider should always have: - **metric-provider-binary** - A binary or script that captures metrics from somewhere in the host system (for instance procfs for CPU utilization) - This file should **always** work standalone and not require a running GMT. Very often this is a native compiled C files. - - See also the `libs/c` directory for some convenience library files that ship with GMT. + - See also the `lib/c` directory for some convenience library files that ship with GMT. - **provider.py** - File containing Python class derived from *BaseMetricProvider* which implements how data is ingested into GMT - **README.md** - An info file specifying what is the ouput of the metric provider in terms of unit and dimension as well as how to execute it on a CLI and what arguments exist. @@ -95,4 +95,4 @@ It is the easiest and also the only way to add back-office functionality to the ## Core functionality - All API code lives in /api and is typically divided by functionality. Every tool of the suite (Eco CI, ScenarioRunner etc.) has it's own file. -- Optimizations live under optimizations. Look at the example file to create a new one. It will be automatically loaded +- Optimizations live under `optimization_providers`. Look at the example file to create a new one. It will be automatically loaded diff --git a/content/en/docs/frontend/customization.md b/content/en/docs/frontend/customization.md index b81232e..724f961 100644 --- a/content/en/docs/frontend/customization.md +++ b/content/en/docs/frontend/customization.md @@ -21,6 +21,14 @@ The first part of the file should not be modified, as these variables are set by ```js API_URL = "__API_URL__" METRICS_URL = "__METRICS_URL__" +ELEPHANT_URL = "__ELEPHANT_URL__" + +ACTIVATE_SCENARIO_RUNNER = __ACTIVATE_SCENARIO_RUNNER__; +ACTIVATE_ECO_CI = __ACTIVATE_ECO_CI__; +ACTIVATE_CARBON_DB = __ACTIVATE_CARBON_DB__; +ACTIVATE_POWER_HOG = __ACTIVATE_POWER_HOG__; +ACTIVATE_SOFTWARE_VIEW = __ACTIVATE_SOFTWARE_VIEW__; +ACTIVATE_AI_OPTIMISATIONS = __ACTIVATE_AI_OPTIMISATIONS__; ``` The later part you can customize. If you for instance want to have the top chart not display all energy metrics, but @@ -29,18 +37,16 @@ rather only the RAPL energy metrics, change accordingly: ```js // old // title and filter function for the top left most chart in the Detailed Metrics / Compare view -const TOP_BAR_CHART_TITLE = 'Energy metrics [mJ]' +const TOP_BAR_CHART_TITLE = 'Energy Metrics'; const top_bar_chart_condition = (metric) => { - if(metric.indexOf('_energy_') !== -1) return true; - return false; + return metric.indexOf('_energy_') !== -1 && (metric.endsWith('_machine') || metric.endsWith('_component')); } // new // title and filter function for the top left most chart in the Detailed Metrics / Compare view -const TOP_BAR_CHART_TITLE = 'RAPL only energy metrics [mJ]' +const TOP_BAR_CHART_TITLE = 'RAPL only energy metrics'; const top_bar_chart_condition = (metric) => { - if(metric.indexOf('_energy_') !== -1 && metric.indexOf('_rapl_') !== -1) return true; - return false; + return metric.indexOf('_energy_') !== -1 && metric.indexOf('_rapl_') !== -1 && (metric.endsWith('_machine') || metric.endsWith('_component')); } ```` diff --git a/content/en/docs/frontend/libraries-and-components.md b/content/en/docs/frontend/libraries-and-components.md index b14daed..78995b4 100644 --- a/content/en/docs/frontend/libraries-and-components.md +++ b/content/en/docs/frontend/libraries-and-components.md @@ -38,8 +38,9 @@ The sidebar is done in flexbox. - All library files which live in `/frontend/dist/` + In the `site.min.css` from Fomantic UI where we removed the @import statement for the external fonts. + We removed the `emoji.min.css` because it contained external imports - + We removed the `flags.min.css` because it contained external imports + We then concatenated all the minified file into a `semantic_reduced.min.css` + + The `flag.min.css` is not part of that concatenation. It ships as a separate file and is only loaded on the pages + that need it (currently `simulation-yearly.html`) - The JS files from Fomantic UI are all included separately, since we don't need most of the components - We use the standard theme for Fomantic UI @@ -51,8 +52,8 @@ On the website you can select a custom build by only including the needed charts Our selection was: -- Only Bar, Line, Pie and Radar chart -- Only Grid coordinate system +- Only Bar, Line, Pie, Radar and Candlestick chart +- Only Grid and Polar coordinate systems - All Components included - Utilities included - Code Compression diff --git a/content/en/docs/general-info/files-and-folders.md b/content/en/docs/general-info/files-and-folders.md index 438fefc..46964bb 100644 --- a/content/en/docs/general-info/files-and-folders.md +++ b/content/en/docs/general-info/files-and-folders.md @@ -37,6 +37,8 @@ Alternatively in the future we might consider running GMT as a module command (` - Includes DB migrations in *SQL* format to run after upgrading from one version to another - `optimization_providers` - Includes the modular *optimization providers* +- `templates` + - Includes the ready-made `usage_scenario` templates for websites and AI models, the re-usable compose partials (e.g. the *Playwright* helpers) and the email templates - `tests` - Includes the *Python* unit- and E2E-tests - `tools` diff --git a/content/en/docs/general-info/units-and-dimensions.md b/content/en/docs/general-info/units-and-dimensions.md index 274bab8..ec3582b 100644 --- a/content/en/docs/general-info/units-and-dimensions.md +++ b/content/en/docs/general-info/units-and-dimensions.md @@ -45,9 +45,17 @@ Identical for Utilization where 0.01 is the smallest value. ## CarbonDB -CarbonDB stores all values as 64-bit floating point values. Respectively: +CarbonDB stores energy and carbon as 64-bit floating point values. Respectively: -- Carbon - micro-Grams (64-bit double precision) -- Energy - micro-Joules (64-bit double precision) +- Carbon - Kilograms [kg] (64-bit double precision) +- Energy - Kilowatt-hours [kWh] (64-bit double precision) + +The carbon intensity is stored next to them as a plain integer in gCO2e/kWh, so its smallest resolution is 1 gCO2e/kWh. + +Note that this is only the storage scheme, and that it differs from what the API accepts: + +- Energy is submitted in micro-Joules [uJ] and converted to kWh on ingest. +- The carbon intensity is submitted in gCO2e/kWh and stored as-is. +- Carbon is never submitted. It is derived on ingest as `energy_kWh * carbon_intensity_g / 1000`. If no intensity was supplied it stays empty until it is backfilled. Thus the lowest resolution is directly derived from the storage scheme and to keep it brief: It is absurdly large, as well as absurdly small :) diff --git a/content/en/docs/help/troubleshooting.md b/content/en/docs/help/troubleshooting.md index 9299522..e83d14a 100644 --- a/content/en/docs/help/troubleshooting.md +++ b/content/en/docs/help/troubleshooting.md @@ -36,9 +36,9 @@ boot. You might then see a message like: -- **Container 'test-container' exited during runtime phase** +- **Container 'test-container' exited during [RUNTIME] (exit code: 0)** - or -- **Container 'test-container' exited during runtime phase** +- **Container 'test-container' failed during [RUNTIME] with exit code 137** In order to properly your container you must instrument it to *just* instantiate and not start anything than *daemons* or background processes. @@ -234,8 +234,9 @@ sudo apt install libglib2.0-dev ``` However, if the error is still present after this command, it might be that -it is not possible to use `lm-sensors` on your system. Comment out the section of the -install script that mentions it and comment it out of your `config.yml`. +it is not possible to use `lm-sensors` on your system. Add the `-S` flag to the +install script to skip installing `lm_sensors` and comment it out of your `config.yml`. +Note that cluster mode and temperature reporters will not work then. ## General tips @@ -244,4 +245,4 @@ does not work that well when orchestrating multiple containers and polling the d - Add the `--debug` switch to your local calls to the `runner.py` to enter the stepping debug mode of the tool. - Add `--allow-unsafe` to the call to `runner.py` and *ports* to your [usage_scenario.yml →]({{< relref "/docs/measuring/usage-scenario" >}}) to access containers through your browser in the host OS to check if the containers are delivering the expected output. - Rebuild the containers with `docker compose down -v` and then `docker compose up -d` -- Re-run the `install.sh` script to get new configuration changes that you maybe have not yet applied after an update +- Re-run the install script for your OS (`install_linux.sh` / `install_mac.sh` / `install_windows.ps1`) to get new configuration changes that you maybe have not yet applied after an update diff --git a/content/en/docs/installation/calibration.md b/content/en/docs/installation/calibration.md index 4f482f8..54b613d 100644 --- a/content/en/docs/installation/calibration.md +++ b/content/en/docs/installation/calibration.md @@ -11,8 +11,8 @@ toc: true Servers vary greatly in how they perform in terms of energy and cooling. This is quite important for us as temperature directly interferes with power consumption. A hot CPU takes significant more energy for the same operation as a cool one. So it is important that we don't run benchmarks right after each other to give the system time to cool down. For this -we have the `sleep_time_after_job` parameter in the [`config.py`](/docs/installation/installation-cluster/) -where you can set how long to sleep between jobs. +we have the `base_temperature_value` parameter in the [`config.yml`](/docs/cluster/installation/) +where you set the temperature the machine must have cooled down to before the next job is started. To find out this value we have a script `tools/calibrate.py` in the Green Metrics Tool [repo](https://github.com/green-coding-solutions/green-metrics-tool). On the system that you want to run your benchmarks on @@ -27,7 +27,8 @@ You can then either get the script to set the correct value for you or set it yo - `--idle-time`: The seconds the system should wait in idle mode. Defaults to 5 minutes - `--stress-time`: The seconds the system should stress the system. Defaults to 2 minutes - `--cooldown-time`: The seconds the system should wait to be back to normal temperature. Defaults to 5 minutes -- `--provider-interval`: The interval in milliseconds for the providers . Defaults to 5000 +- `--provider-interval`: The interval in milliseconds for the providers . Defaults to 2000 +- `--temperature-increase`: The delta in centi°C the temperature must increase under stress. Defaults to 1000 - `--stress-command`: The command to stress the system with. Defaults to stress-ng - `--log-level`: Logging level (debug, info, warning, error, critical) - `--output-file`: Path to the output log file. @@ -40,18 +41,24 @@ If the program exits because of an error you can use the return code to see why: 2) stress command failed 3) temperature never falls below mean 4) outliers in idle measurement +5) temperature is not raising under stress ## Output Important values that are extracted: ```text -[INFO] - Cool down time is 4 seconds -[DEBUG] - Power mean is {'Package_0': 3224.3333333333335} -[DEBUG] - Temperature means are {'acpitz-acpi-0_temp1': 5433.333333333333, 'coretemp-isa-0000_Package-id-0': 5400.0} +[INFO] 2026-07-16 09:12:44,317 - System idle measurement successful +[INFO] 2026-07-16 09:12:44,317 - Mean Energy: 3224.33 uJ +[INFO] 2026-07-16 09:12:44,317 - Mean Power: 32.24 W +[INFO] 2026-07-16 09:12:44,318 - Std. Dev: 12.5 uJ +[INFO] 2026-07-16 09:12:44,318 - Std. Dev (rel): 0.39 % +[INFO] 2026-07-16 09:14:02,905 - Peak system energy is: 9871.5 uJ +[INFO] 2026-07-16 09:14:02,905 - Peak system power is: 98.72 W +[INFO] 2026-07-16 09:14:02,906 - Effective energy overhead (rel.) is: 1.83 % ``` -Please remember that we multiply the values with 100 to avoid integers in the database +Please remember that all values are stored as integers in the database. Temperatures are therefore multiplied by 100 and stored as centi°C, while energy is multiplied by 1,000,000 and stored as micro-Joules. Calibration process showing power measurement values diff --git a/content/en/docs/installation/installation-linux.md b/content/en/docs/installation/installation-linux.md index 26c27b8..1471c2f 100644 --- a/content/en/docs/installation/installation-linux.md +++ b/content/en/docs/installation/installation-linux.md @@ -14,7 +14,7 @@ Currently the following distributions have been tested and are fully supported: - Ubuntu 24.04 (Desktop and Server) - Ubuntu 22.04 (Desktop and Server) -- Fedora 38 +- Fedora 43 (Desktop and Server) For the server variants we recommend installing with the *minimal* option set for a low overhead system with best reproducability of measurements and apply [NOP Linux]({{< relref "/docs/cluster/nop-linux" >}}) enhancements after. @@ -25,7 +25,7 @@ The following distributions have been tested, but require manual work: - Ubuntu 22.10 (works for development, but [cluster installation]({{< relref "/docs/cluster/installation" >}}) has different names for timers) {{< callout context="note" icon="outline/info-circle" >}} -If you want to develop on macOS or Windows please use the appropriate installation description: +If you want to develop on macOS or Windows please use the appropriate installation description: {{< /callout >}} ## Downloading and installing required packages @@ -208,7 +208,7 @@ is running on port `80` or `443` Please note that whenever you run the Green Metrics Tool you have to first activate the python `venv`. {{< callout context="note" icon="outline/info-circle" >}} -Note for ARM systems: Please use the '-r' flag, which will tell the script to not install the 'msr-tools' package. A tool that is only available on Intel and AMD systems. +Note for ARM systems: Please use the '-R' flag, which will tell the script to not install the 'msr-tools' package. A tool that is only available on Intel and AMD systems. {{< /callout >}} What you might want to add: @@ -298,7 +298,7 @@ Only a limited subset is activated by default, which are know to work guaranteed This is done by un-commenting the respective lines in the `config.yml`. To activate the RAPL CPU energy provider you would have to uncomment these two lines for instance: ```yml -cpu.energy.rapl.msr.component.provider.CpuEnergyRaplMsrComponentProvider: +cpu_energy_rapl_msr_component: sampling_rate: 99 ``` @@ -308,7 +308,7 @@ Also - Some metric providers need extra setup before they work: ### LM-Sensors -The required libraries are installed automatically via the `install-linux.sh` call. Some modifications need to be made to your `config.yml` file though, which are detailed in the lm-sensors metric provider [documentation →]({{< relref "/docs/measuring/metric-providers/lm-sensors" >}}), along with further details regarding prerequisites. +The required libraries are installed automatically via the `install_linux.sh` call. Some modifications need to be made to your `config.yml` file though, which are detailed in the lm-sensors metric provider [documentation →]({{< relref "/docs/measuring/metric-providers/lm-sensors" >}}), along with further details regarding prerequisites. ### XGBoost @@ -371,7 +371,7 @@ The change is done in the `/docker/compose.yml` file. green-coding-nginx: [...] ports: - - 9142:80 # change this to 80:80 + - 9142:9142 # change this to 80:9142 ``` ### SSL diff --git a/content/en/docs/installation/installation-macos.md b/content/en/docs/installation/installation-macos.md index 2562306..11831cf 100644 --- a/content/en/docs/installation/installation-macos.md +++ b/content/en/docs/installation/installation-macos.md @@ -70,22 +70,25 @@ On macOS you have two options for metric provider setups: -You will need to disable all providers and enable the: +The metric providers are partitioned by architecture in the `config.yml`, so only the providers under the `macos:` and +`common:` keys are loaded on a Mac. There is no need to disable the Linux providers. + +Under `macos:` you can enable: ```yml -powermetrics.provider.PowermetricsProvider: - sampling_rate: 100 +powermetrics: + sampling_rate: 199 # If you set this value too low powermetrics will not be able to accommodate the timing. We recommend no lower than 199 ms ``` Or to use the model approach use: ```yml - cpu.utilization.mach.system.provider.CpuUtilizationMachSystemProvider: + cpu_utilization_mach_system: sampling_rate: 99 -# and either one of the model providers -psu.energy.ac.xgboost.machine.provider.PsuEnergyAcXgboostMachineProvider: +# and either one of the model providers, which live under the 'common:' key +psu_energy_ac_xgboost_machine: # ... including its configuration options -psu.energy.ac.sdia.machine.provider.PsuEnergyAcSdiaMachineProvider: +psu_energy_ac_sdia_machine: # ... including its configuration options ``` @@ -99,7 +102,7 @@ None of the providers provide insights into the Docker VM directly. Only host le You can now connect to the db directly on port 9573, which is exposed to your host system.\ This exposure is not strictly needed for the green metrics tool to run, but is useful if you want to access the db directly. If you do not wish to do so, just remove the `9573:9573` entry in the `compose.yml` file. -The database name is `green-coding`, user is `postgres`, and the password is what you have specified during the `install.sh` run, and can be found in the `compose.yml` file. +The database name is `green-coding`, user is `postgres`, and the password is what you have specified during the `install_mac.sh` run, and can be found in the `compose.yml` file. ### Dockerfiles architecture explanation: diff --git a/content/en/docs/installation/installation-windows.md b/content/en/docs/installation/installation-windows.md index d58578a..45e5695 100644 --- a/content/en/docs/installation/installation-windows.md +++ b/content/en/docs/installation/installation-windows.md @@ -75,7 +75,7 @@ References: To be able to access the frontend and the API of the GMT, you have to add the URLs to the hosts file on your Windows host system: `C:\Windows\System32\drivers\etc\hosts` ```plain -127.0.0.1 green-coding-postgres-container +127.0.0.1 green-coding-postgres-container green-coding-redis-container 127.0.0.1 api.green-coding.internal metrics.green-coding.internal ``` @@ -109,23 +109,23 @@ With WSL hardware-near metric providers like RAPL are not available. However, for testing your usage scenarios you can use at least the following metric providers by uncommenting them in the `config.yml: - System CPU utilization via procfs - - Config: `cpu.utilization.procfs.system.provider.CpuUtilizationProcfsSystemProvider` + - Config: `cpu_utilization_procfs_system` - Documentation: [Measuring/Metric Providers/CPU % - procfs - system]({{< relref "/docs/measuring/metric-providers/cpu-utilization-procfs-system" >}}) - Container CPU utilization via cgroupv2 - - Config: `cpu.utilization.cgroup.container.provider.CpuUtilizationCgroupContainerProvider` + - Config: `cpu_utilization_cgroup_container` - Documentation: [Measuring/Metric Providers/CPU % - cgroup - container]({{< relref "/docs/measuring/metric-providers/cpu-utilization-cgroup-container" >}}) - Container memory usage via cgroupv2 - - Config: `memory.used.cgroup.container.provider.MemoryUsedCgroupContainerProvider` + - Config: `memory_used_cgroup_container` - Documentation: [Measuring/Metric Providers/Memory Used - cgroup - container]({{< relref "/docs/measuring/metric-providers/memory-used-cgroup-container" >}}) - Container network I/O via cgroupv2 - **only available with native Docker installation, not Docker Desktop for Windows** - - Config: `network.io.cgroup.container.provider.NetworkIoCgroupContainerProvider` + - Config: `network_io_cgroup_container` - Documentation: [Measuring/Metric Providers/Network IO - cgroup - container]({{< relref "/docs/measuring/metric-providers/network-io-cgroup-container" >}}) - Container disk I/O via cgroupv2 - - Config: `disk.io.cgroup.container.provider.DiskIoCgroupContainerProvider` + - Config: `disk_io_cgroup_container` - Documentation: tbd. - Machine energy consumption via XGBoost (ML-based estimation) - - Config: `psu.energy.ac.xgboost.machine.provider.PsuEnergyAcXgboostMachineProvider` + - Config: `psu_energy_ac_xgboost_machine` - Documentation: [Measuring/Metric Providers/PSU Energy - AC - XGBoost - Machine]({{< relref "/docs/measuring/metric-providers/psu-energy-xgboost-machine" >}}) You have to disable all other providers in your `config.yml`. diff --git a/content/en/docs/installation/uninstallation.md b/content/en/docs/installation/uninstallation.md index fbb6868..6e068ee 100644 --- a/content/en/docs/installation/uninstallation.md +++ b/content/en/docs/installation/uninstallation.md @@ -14,7 +14,12 @@ You can run it like this: bash uninstall.sh ``` -The script will remove all installed python libraries, all docker containers and optional +The script will remove all installed python libraries, all docker containers and images and optional also the pre-install requirements like docker etc. -It has the option to keep your data by leaving *PostgreSQL* and it's *docker volume* installed +It has the option to keep your data: The *PostgreSQL* container and image are always removed, but the +*docker volume* that holds your measurement data is only removed if you confirm the prompt. + +{{< callout context="caution" icon="outline/alert-triangle" >}} +As its very last step the script deletes the whole repository directory it is run from (`rm -fR`). Make sure you have copied out anything you want to keep, for example your `config.yml`, before running it. +{{< /callout >}} diff --git a/content/en/docs/installation/updating.md b/content/en/docs/installation/updating.md index a429d41..fd5064a 100644 --- a/content/en/docs/installation/updating.md +++ b/content/en/docs/installation/updating.md @@ -41,11 +41,14 @@ changed, then they need to be installed with: ```bash python3 -m pip install -r ~/green-metrics-tool/requirements.txt +python3 -m pip install -r ~/green-metrics-tool/docker/requirements.txt +python3 -m pip install -r ~/green-metrics-tool/metric_providers/psu/energy/ac/xgboost/machine/model/requirements.txt ``` ## Re-Run the install script -After every new `git pull` you should run the `install.sh` script to get the +After every new `git pull` you should re-run the install script for your platform +(`install_linux.sh`, `install_mac.sh` or `install_windows.ps1`) to get the newest binaries and configuration params for the Green Metrics Tool. It will ask you for the database password every time. If you want to keep the database @@ -64,7 +67,7 @@ To run a migration either paste the SQL code directly to the DB or use the `impo Example: ```bash -python3 tools/import_data.py ./migrations/2023_07_08_indices.sql +python3 tools/import_data.py ./migrations/2026_07_07_remove_phase_padding.sql ``` ## Read the GitHub release notes diff --git a/content/en/docs/measuring/best-practices.md b/content/en/docs/measuring/best-practices.md index 2278b5f..30ce138 100644 --- a/content/en/docs/measuring/best-practices.md +++ b/content/en/docs/measuring/best-practices.md @@ -121,7 +121,7 @@ energy measurements are not false-high. A good number for this has emerged in ou a 30+ core machine this value might be higher. We are currently working on a [calibration script](https://github.com/green-coding-solutions/green-metrics-tool/issues/355) to determine this exact value for a particular system. -If you are using a standard cronjob mechanism to trigger the GMT you can use the `post-test-sleep` to force a fixed sleep time. +If you are using a standard cronjob mechanism to trigger the GMT you can use the `--measurement-post-test-sleep` switch of the `runner.py` to force a fixed sleep time. ### 12. Mount your `/tmp` on `/tmpfs` @@ -162,11 +162,11 @@ The reason for this is that you do not want to run into a lock-step sampling err The GMT comes with many sytem checks that only issue a warning in the default configuration. -We recommend setting `system_check_treshold` to **2** in your production setup of the [Configuration]({{< relref "configuration" >}}) +We recommend running with `--measurement-system-check-threshold` set to **2** in your production setup, so that a run also fails on warnings and not only on errors. On our [Hosted Service]({{< relref "measuring-service" >}}) this is the per-user setting `measurement.system_check_threshold`. ### 17. Idle Duration -If you are trying to calculate an energy per container you should set the `idle-duration` configuration value high enough so you get a stable value to base the offset on. +If you are trying to calculate an energy per container you should set the `--measurement-idle-duration` switch of the `runner.py` high enough so you get a stable value to base the offset on. We recommend at least *120 s* if you have a non-controlled cluster system. *60 s* if you are running on an [accuracy controlled]({{< relref "accuracy-control" >}}) cluster like for instance our [Measurement Cluster]({{< relref "measurement-cluster" >}}) diff --git a/content/en/docs/measuring/carbon/grid-carbon-intensity.md b/content/en/docs/measuring/carbon/grid-carbon-intensity.md index 12999cb..3b9b97f 100644 --- a/content/en/docs/measuring/carbon/grid-carbon-intensity.md +++ b/content/en/docs/measuring/carbon/grid-carbon-intensity.md @@ -24,7 +24,7 @@ In the [Software Carbon Intensity (SCI)]({{< relref "sci" >}}) metric this value ## Carbon Intensity Providers -You select how the grid carbon intensity is determined by activating one of the carbon intensity providers in the `metric-providers` section of your `config.yml`. The following providers are available: +You select how the grid carbon intensity is determined by activating one of the carbon intensity providers in the `metric_providers` section of your `config.yml`. The following providers are available: - **Static** (`CarbonIntensityStaticMachineProvider`) — Uses a fixed value you configure. This is the direct replacement for the old `sci.I` value and gives you **reproducible measurements** and **fair comparisons** (every run on the same machine uses the same baseline). - **Electricity Maps** ([CarbonIntensityElectricitymapsMachineProvider]({{< relref "../metric-providers/carbon-intensity-electricitymaps-machine" >}})) — Fetches the real grid carbon intensity for your region and measurement window from the [Electricity Maps API](https://www.electricitymaps.com/). @@ -32,11 +32,11 @@ You select how the grid carbon intensity is determined by activating one of the ### Configuration -The static provider is the most common choice if you want a stable baseline. You configure it under `measurement.metric-providers.common` in your `config.yml`: +The static provider is the most common choice if you want a stable baseline. You configure it under `measurement.metric_providers.common` in your `config.yml`: ```yml measurement: - metric-providers: + metric_providers: common: carbon_intensity_static_machine: # Static carbon intensity in gCO2e/kWh. Replaces the former SCI 'I' value. diff --git a/content/en/docs/measuring/carbon/network-carbon-intensity.md b/content/en/docs/measuring/carbon/network-carbon-intensity.md index 7119e63..be31f35 100644 --- a/content/en/docs/measuring/carbon/network-carbon-intensity.md +++ b/content/en/docs/measuring/carbon/network-carbon-intensity.md @@ -34,7 +34,7 @@ You can configure the network energy intensity as part of the [SCI]({{< relref " ```yml sci: - N: 0.001875 # unit: kWh/GB + N: 0.04106063 # unit: kWh/GB ``` GMT calculates the network carbon intensity as: diff --git a/content/en/docs/measuring/carbon/sci.md b/content/en/docs/measuring/carbon/sci.md index 03f29bc..a010783 100644 --- a/content/en/docs/measuring/carbon/sci.md +++ b/content/en/docs/measuring/carbon/sci.md @@ -80,9 +80,12 @@ sci: EL: 4 # means 4 years of usage RS: 1 # means we use 1/1 = 100% of the machine. Bare metal. No virtualization TE: 181000 # Example value for a laptop taken from https://dataviz.boavizta.org/terminalimpact. Value is in g - I: 334 # The number 334 that comes as default is for Germany from 2024. Value in gCO2e/kWh ``` +The grid carbon intensity (*I*) is **not** configured here. It is supplied by a dedicated carbon intensity +metric provider, which lets you choose between a static value and live grid data on a per-run basis. +See [Grid Carbon Intensity →]({{< relref "grid-carbon-intensity" >}}) for how to activate and configure one. + ## Display The metric will is calculated per phase in which it occures and then aggregated in the RUNTIME as total. @@ -103,7 +106,8 @@ The components of the SCI are attributed by the GMT as follows: - If none is activated machine energy will be excluded from the SCI. - A *Network IO* provider must be activated to populate this value with the network energy. - If none is activated network energy will be excluded from the SCI. -- *I:* Configured in the `config.yml`. Set the intensity of your used grid location +- *I:* Supplied by a *carbon intensity* metric provider, which sets the intensity of your used grid location. You can choose between a static value and live grid data. See [Grid Carbon Intensity →]({{< relref "grid-carbon-intensity" >}}) + - If none is activated no carbon can be attributed and the SCI will not be calculated. - *M:* Configured in the `config.yml`. Set the embodied carbon of your used machine ## Example applications diff --git a/content/en/docs/measuring/comparing-measurements.md b/content/en/docs/measuring/comparing-measurements.md index 4b82439..b7cd572 100644 --- a/content/en/docs/measuring/comparing-measurements.md +++ b/content/en/docs/measuring/comparing-measurements.md @@ -33,7 +33,7 @@ Comparison is currently possible for measurements that are: The tool will let you know if you try to compare measurements that can't be compared. -To trigger a comparison in the frontend just tick the boxes of the runs you wish to compare and click the *Compare Runs* button. +To trigger a comparison in the frontend just tick the boxes of the runs you wish to compare and click the *Compare: N Run(s)* button. Triggering Compare mode @@ -51,7 +51,7 @@ Graphs will also include the confidence interval. Comparing measurements should help raise awareness of software energy use over time. -## Expert compare mode +## Forcing a comparison mode In some instances the GMT will not allow certain comparisons. For instance when you compare different machines and also different repositories. @@ -60,15 +60,16 @@ A comparion like this *sounds unreasonable* for the GMT as machine and comparing But still there might be instances when you want to force a certain comparison type. For instance when the repository is basically the same as the old one, just has been renamed. GMT does not understand repository renaming currently. -In that or similar cases you can override the default *comparison mode auto detection* and use the *Export Mode*. +In that or similar cases you can override the default *comparison mode auto detection*. -Navigate to *Settings* and toggle *Expert compare mode*. +As soon as you tick at least one run a *Mode* dropdown appears next to the *Compare* button. It defaults to *Auto*, which +is the comparison mode auto detection. To force a mode set it to one of *Branches*, *Commits*, *Machines*, +*Usage Scenarios*, *Variables*, *Repos* or *Simple Table*. Your selection is remembered for the next comparison. -A new box will appear when comparing settings where you can force a mode. For instance treating runs from different -repositories and branches with different commits, which however have run on the same machine as a *Machine* comparison -will effectively compare them as being just repeated runs on the same machine. +For instance treating runs from different repositories and branches with different commits, which however have run on the +same machine as a *Machines* comparison will effectively compare them as being just repeated runs on the same machine. -Expert compare mode +Forcing a comparison mode Your runs must in any case have one common demoniator, that has at max two values. For instance: @@ -82,13 +83,17 @@ Your runs must in any case have one common demoniator, that has at max two value When running a comparison between different commits, different machines etc. the GMT will also compute a *T-test* for the two samples. -It will calculate the *T-test* for the means of two independent samples of scores assuming even independent variances. (Some might know this test also as *Welch’s t-test* or *Welch test*) +It will calculate the *T-test* for the means of two independent samples of scores without assuming equal variances. (Some might know this test also as *Welch’s t-test* or *Welch test*) If the *p-value* is lower than **0.05** GMT will show the result as significant. GMT will provide the *p-value* directly in the API output of the comparison. -In the frontend it will be shown with a green / red indicator for the significance. Green meaning significant. -Or it will tell you if a comparison could not be made in case there where too many missing values or the metric was not present in all runs. +In the frontend the *Significant (T-Test)* column will read *Significant*, or *not significant / no-test*. The latter also +covers the case that no test could be made because there where too many missing values or the metric was not present in +all runs. + +Note that the green / red coloring is not an indicator for significance. It is applied to the *Change* column only and +merely tells you if the value went up (red) or down (green). Green Metrics Tool T-test comparison showing statistical significance indicators @@ -102,5 +107,6 @@ This question is very typical as you will have a set of a couple of runs once me If the *p-value* is lower than **0.05** GMT will show the result as significant. GMT will provide the *p-value* directly in the API output of the comparison. -In the frontend it will be shown with a green / red indicator for the significance. Green meaning significant. -Or it will tell you if a comparison could not be made in case there where too many missing values or the metric was not present in all runs. + +Since repeated runs have no second key to compare against, the detailed metrics table in the frontend has no +*Significant (T-Test)* column in this case. The *p-value* is only available through the API. diff --git a/content/en/docs/measuring/configuration.md b/content/en/docs/measuring/configuration.md index c0deb38..61f96dd 100644 --- a/content/en/docs/measuring/configuration.md +++ b/content/en/docs/measuring/configuration.md @@ -43,8 +43,9 @@ cluster: client: sleep_time_no_job: 300 jobs_processing: "random" - shutdown_on_job_no: False update_os_packages: True + # the value is passed to systemctl, so it must be a verb like "suspend" or "poweroff". False disables it + shutdown_on_job_no: suspend reboot_after_seconds: False # These two parameters have only effect in cluster mode. When using CLI they will be set via flags --docker-prune and --full-docker-prune only docker_prune: True @@ -56,15 +57,25 @@ cluster: name: "Measurement control Workload" uri: "https://github.com/green-coding-solutions/measurement-control-workload" filename: "usage_scenario.yml" - branch: "main" + branch: "event-bound" comparison_window: 5 - threshold: 0.01 phase: "004_[RUNTIME]" metrics: - - "psu_energy_ac_mcp_machine" - - "psu_power_ac_mcp_machine" - - "cpu_power_rapl_msr_component" - - "cpu_energy_rapl_msr_component" + psu_energy_ac_mcp_machine: + threshold: 0.01 # 1% + type: stddev_rel + psu_power_ac_mcp_machine: + threshold: 0.01 # 1% + type: stddev_rel + cpu_power_rapl_msr_component: + threshold: 0.01 # 1% + type: stddev_rel + cpu_energy_rapl_msr_component: + threshold: 0.01 # 1% + type: stddev_rel + network_total_cgroup_container: + threshold: 10000 # 10 kB + type: stddev machine: id: 1 @@ -76,22 +87,22 @@ machine: measurement: full_docker_prune_whitelist: - - gcr.io/kaniko-project/executor - metric-providers: + - martizih/kaniko:slim + metric_providers: linux: - cpu.utilization.cgroup.container.provider.CpuUtilizationCgroupContainerProvider: - sampling_rate: 100 - cpu.energy.RAPL.MSR.system.provider.CpuEnergyRaplMsrSystemProvider: - sampling_rate: 100 - memory.total.cgroup.container.provider.MemoryTotalCgroupContainerProvider: - sampling_rate: 100 - cpu.time.cgroup.container.provider.CpuTimeCgroupContainerProvider: - sampling_rate: 100 + cpu_utilization_cgroup_container: + sampling_rate: 99 + cpu_energy_rapl_msr_component: + sampling_rate: 99 + memory_used_cgroup_container: + sampling_rate: 99 + cpu_time_cgroup_container: + sampling_rate: 99 # ... admin: notification_email: False - notification_email_bcc: False + email_bcc: False error_file: False error_email: False @@ -125,22 +136,33 @@ See [Machine Baseline Checks →]({{< relref "/docs/cluster/machine-baseline-che ### measurement -- `full_docker_prune_whitelist` **[list]**: A list of image names (without tag) or image IDs (short form) that will be whitelisted when `--full-docker-prune` is active. Images listed here will not be pruned. Useful for cluster installations where non security critical images shall be kept that take long to download. -- `metric-providers`: +- `full_docker_prune_whitelist` **[list]**: A list of images that will be whitelisted when `--full-docker-prune` is active. Images listed here will not be pruned. Useful for cluster installations where non security critical images shall be kept that take long to download. + + Every entry is matched as a *substring* against the `repository:tag` of each local image, so a tag may be included to whitelist only a specific version. Image IDs do not work. +- `metric_providers`: + `linux`/`macos`/`common` **[string]**: Specifies under what system the metric provider can run. Common implies it could run on either. * `METRIC_PROVIDER_NAME` **[string]**: Key specifies the Metric Provider. [Possible Metric Providers →]({{< relref "/docs/measuring/metric-providers/metric-providers-overview" >}}) * `METRIC_PROVIDER_NAME.sampling_rate` **[integer]**: sampling rate in ms +The name of a metric provider is a flat snake_case key like `cpu_energy_rapl_msr_component`. GMT derives +the module and the class to load from that name, so the older dotted class-path notation +(`cpu.energy.RAPL.MSR.component.provider.CpuEnergyRaplMsrComponentProvider`) is no longer valid and +will fail on import. + +All keys below a metric provider are passed to it as configuration parameters, so only supply keys +that the provider actually accepts. + Some metric providers have unique configuration params: -- PsuEnergyAcXgboostSystemProvider +- `psu_energy_ac_xgboost_machine` + + Requires `HW_CPUFreq`, `CPUChips`, `CPUThreads`, `TDP` and `HW_MemAmountGB`. Optional are `CPUCores`, `Hardware_Availability_Year` and `VHost_Ratio`. + + This provider does not sample, so it accepts **no** `sampling_rate` key. Supplying one will make the run fail. + Please look at the always current documentation to understand what values to plug in here: [XGBoost SPECPower Model documentation](https://github.com/green-coding-solutions/spec-power-model) Also note that some providers are deactivated by default, because they either need additional configuration parameters, extra hardware or a specially configured system. Once you have set them up you can uncomment the line. In this example for instance -the line `psu.energy.ac.xgboost.system.provider.PsuEnergyAcXgboostSystemProvider` and all +the line `psu_energy_ac_xgboost_machine` and all the lines directly below it. ### admin @@ -149,7 +171,7 @@ The `admin` key provides no configuration for essential configurations like for email behaviour if configured - `notification_email` **[str|bool]**: This address will get an email, for any error or new project added etc. -- `notification_email_bcc` **[str|bool]**: This email will always get a copy of every notification email sent, even for user-only mails like the "Your report is ready" mail. +- `email_bcc` **[str|bool]**: This email will always get a copy of every notification email sent, even for user-only mails like the "Your report is ready" mail. - `error_file` **[str|bool]**: Takes a file path to log all the errors to it. This is disabled if False - `error_email` **[str|bool]**: Sends an error notification also via email. This is disabled if False @@ -188,11 +210,14 @@ electricity_maps_token: 'MY_TOKEN' Settings that are specifc to a user and apply to all machines that you are measuring on equally are to be configured via the Dashboard. For local installations these are to be found under [https://metrics.green-coding.internal:9142/settings.html](https://metrics.green-coding.internal:9142/settings.html). If you use our [Hosted Service](https://metrics.green-coding.io/) you find it at [https://metrics.green-coding.io/settings.html](https://metrics.green-coding.io/settings.html) -- `disabled_metric_providers` **[list]**: Providers to disable in CamelCase format. - + Example: *NetworkConnectionsProxyContainerProvider* -- `flow-process-duration` **[integer]**: Max. duration in seconds for how long one flow should take. Timeout-Exception is thrown if exceeded. -- `total-duration` **[integer]**: Max. duration in seconds for how long the whole run may take. Including building containers, baseline, idle, runtime and removal phases. -- `dev-no-sleeps` **[integer]**: Does not sleep in between phases and for cool-down periods. Beware that this will speed up runs on the cluster but render them invalid. -- `dev-no-optimizations` **[integer]**: De-activates running the optimizations after a measurement. +- `disabled_metric_providers` **[list]**: Providers to disable even if they are configured on the machine. Only these two values are accepted: + + *network_connections_tcpdump_system* + + *network_connections_proxy_container* +- `flow_process_duration` **[integer]**: Max. duration in seconds for how long one process in a flow should take. Timeout-Exception is thrown if exceeded. +- `total_duration` **[integer]**: Max. duration in seconds for how long the whole run may take. Including building containers, baseline, idle, runtime and removal phases. +- `dev_no_sleeps` **[bool]**: Does not sleep in between phases and for cool-down periods. Beware that this will speed up runs on the cluster but render them invalid. +- `skip_optimizations` **[bool]**: De-activates running the optimizations after a measurement. + +The equivalent when running the `runner.py` directly are the [runner.py switches →]({{< relref "runner-switches" >}}).
Dashboard Settings for GMT Measurements
diff --git a/content/en/docs/measuring/containerizing-applications.md b/content/en/docs/measuring/containerizing-applications.md index 4e169f8..37a68b2 100644 --- a/content/en/docs/measuring/containerizing-applications.md +++ b/content/en/docs/measuring/containerizing-applications.md @@ -213,7 +213,7 @@ networks: example-network: services: -# There is no container_name directive. All services keys act directly as container names +# The container_name directive is optional. If you omit it the service key acts as the container name db-container: # If you build your file with docker compose in the example above this image name should be the one you have now locally image: demo_app_db diff --git a/content/en/docs/measuring/debugging.md b/content/en/docs/measuring/debugging.md index 1eb6b35..1ef3773 100644 --- a/content/en/docs/measuring/debugging.md +++ b/content/en/docs/measuring/debugging.md @@ -22,7 +22,7 @@ the *usage scenario* without having to go through all previous steps. It will al Please note that this only works with a local repository. If your repository is online only atm clone it first to your local filesystem. This allows for editing files while running a *usage scenario* A typical call looks like this: -`python3 --uri MY_LOCAL_PATH --name Testing --allow-unsafe --dev-no-metrics --dev-no-sleeps --dev-cache-build --dev-flow-timetravel` +`python3 runner.py --uri MY_LOCAL_PATH --name Testing --allow-unsafe --dev-no-metrics --dev-no-sleeps --dev-cache-build --dev-flow-timetravel` ### --debug flag @@ -83,4 +83,3 @@ Typically when a *flow command* does not end it is because the process is really We recommend you check if the container ran into configured memory / cpu limits of the docker orchestrator. Either through linux system tools or through *docker stats* if you have system access. If you are using the **GMT Cluster / SaaS** you can let the process run into the maximum time limit to see the metrics timelines to understand memory and CPU usage and possible limits hit. ->>>>>>> main diff --git a/content/en/docs/measuring/deleting-measurements.md b/content/en/docs/measuring/deleting-measurements.md index 73abcf3..120faf4 100644 --- a/content/en/docs/measuring/deleting-measurements.md +++ b/content/en/docs/measuring/deleting-measurements.md @@ -13,15 +13,15 @@ to prune the database of these failed measurements. Please run: ```bash -python3 tools/prune_db.py +python3 tools/prune_db.py failed-runs ``` ## Removing all measurements in the CLI -If you instead want to remove all measurements you can use the `--all` switch: +If you instead want to remove all measurements you can use the `all` mode: ```bash -python3 tools/prune_db.py --all +python3 tools/prune_db.py all ``` ## Why is there no function in the online interface? diff --git a/content/en/docs/measuring/interacting-with-applications.md b/content/en/docs/measuring/interacting-with-applications.md index 74b6ba0..ab2503b 100644 --- a/content/en/docs/measuring/interacting-with-applications.md +++ b/content/en/docs/measuring/interacting-with-applications.md @@ -38,14 +38,15 @@ This is the resulting `usage_scenario.yml` file: ```yaml name: Stress Container One Core 5 Seconds author: Arne Tarara +description: Stresses one core for 5 seconds architecture: linux services: simple-load-container: image: alpine setup-commands: - command: apk add stress-ng - - flow: + +flow: - name: Stress container: simple-load-container commands: @@ -81,6 +82,10 @@ on your system and application. The names in this example follow the naming in the example from [containerizing applications →]({{< relref "containerizing-applications" >}}) ```yaml +name: Wordpress Example Flow +author: Arne Tarara +description: Browses some sample subsites of the Wordpress demo application + networks: example-network: services: diff --git a/content/en/docs/measuring/measuring-ai-ml-applications.md b/content/en/docs/measuring/measuring-ai-ml-applications.md index 872a7cc..3145a0f 100644 --- a/content/en/docs/measuring/measuring-ai-ml-applications.md +++ b/content/en/docs/measuring/measuring-ai-ml-applications.md @@ -17,7 +17,7 @@ See [our example ML example application](https://github.com/green-coding-solutio The simplest way is to use [ollama](https://ollama.com) as a manager and encapsulate it inside of the GMT. See [our example ollama LLM example application](https://github.com/green-coding-solutions/example-applications/tree/main/ai-model) to have a usage scenario to get started. -This contains a [usage scenario to run on the CPU only](https://github.com/green-coding-solutions/example-applications/blob/main/ai-model/usage_scenario_gpu.yml) and one +This contains a [usage scenario to run on the CPU only](https://github.com/green-coding-solutions/example-applications/blob/main/ai-model/usage_scenario.yml) and one that [runs on the GPU](https://github.com/green-coding-solutions/example-applications/blob/main/ai-model/usage_scenario_gpu.yml). For the latter scenario you can see that the GPU must be activated for the docker container by passing the *docker run arg* `--gpus=all`. This functionaly requires the [NVIDIA container toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) to be installed on your host. diff --git a/content/en/docs/measuring/measuring-containers.md b/content/en/docs/measuring/measuring-containers.md index 2736daa..53be061 100644 --- a/content/en/docs/measuring/measuring-containers.md +++ b/content/en/docs/measuring/measuring-containers.md @@ -54,8 +54,3 @@ We currently have a beta feature to be launched in Summer 2025 that utilizes AMD The GMT will utilize a `taskset` to pin the container to a distinct core. Since no other processes are running on your benchmarking systems in [Green Metrics Tool Cluster Hosted Service →]({{< relref "/docs/measuring/measuring-service" >}}) the values are very reliable. Private beta opens Summer 2025. If you are interested shoot us an email to [info@green-coding.io](mailto:info@green-coding.io) - -- The energy of the browser is measured to display and render the page -- The network transfer energy is measured that was needed to download the HTML and page assets - -To isolate this as best as possible GMT orchestrates a reverse proxy, warms up the cache by pre-loading the full page once and only then does the final measurement. diff --git a/content/en/docs/measuring/measuring-gui-applications.md b/content/en/docs/measuring/measuring-gui-applications.md index e1ebf10..edd6bef 100644 --- a/content/en/docs/measuring/measuring-gui-applications.md +++ b/content/en/docs/measuring/measuring-gui-applications.md @@ -106,7 +106,7 @@ If you are running GMT unattended in cluster mode you must ensure two things: Add `xhost +local:docker` to `~/.xprofile` -Example: `$ xhost +" >> ~/.xprofile` +Example: `$ echo "xhost +local:docker" >> ~/.xprofile` #### Wayland autostart file diff --git a/content/en/docs/measuring/measuring-websites.md b/content/en/docs/measuring/measuring-websites.md index ef9374f..137e0ab 100644 --- a/content/en/docs/measuring/measuring-websites.md +++ b/content/en/docs/measuring/measuring-websites.md @@ -11,9 +11,9 @@ GMT can also measure websites and takes a multi-dimensional approach here: - The energy of the browser is measured to display and render the page - The network transfer energy is measured that was needed to download the HTML and page assets -To isolate this as best as possible GMT orchestrates a reverse proxy, warms up the cache by pre-loading the full page once and only then does the final measurement. +By default the page is measured *uncached*. To isolate the render energy better GMT can optionally orchestrate a reverse proxy and warm up the cache by pre-loading the full page once before doing the final measurement. See [Caching with a Reverse Proxy](#caching-with-a-reverse-proxy) below. -**Warning:** Measuring websites is very tricky! GMT shaves off some of the caveats by using reverse proxys and cache pre-loading to make results more reliable. Since measurement load times are in milliseconds range you must have [Metric Providers]({{< relref "/docs/measuring/metric-providers/" >}}) with very high *sampling_rates* connected. **2ms** is a good value. Also website measurements are really only realiable in a [controlled cluster]({{< relref "/docs/cluster/" >}}) with [accuracy control]({{< relref "/docs/cluster/accuracy-control" >}}). +**Warning:** Measuring websites is very tricky! GMT can shave off some of the caveats by using reverse proxys and cache pre-loading to make results more reliable. Since measurement load times are in milliseconds range you must have [Metric Providers]({{< relref "/docs/measuring/metric-providers/" >}}) with very high *sampling_rates* connected. **2ms** is a good value. Also website measurements are really only realiable in a [controlled cluster]({{< relref "/docs/cluster/" >}}) with [accuracy control]({{< relref "/docs/cluster/accuracy-control" >}}). ## Quick website measuring @@ -23,7 +23,9 @@ In the root folder you find the `run-template.sh` file. Measure a sample query like this: `bash run-template.sh website "https://www.green-coding.io"` -It will download the needed containers, setup them up and run the measurement. Once you got this quick measurement running iterate on it by extending the [example measurement file](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/templates/website/usage_scenario.yml) with more steps, for instance measuring all the sub-pages on your domain +It will download the needed containers, setup them up and run the measurement. This runs the [example measurement file](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/templates/website/usage_scenario.yml), which opens the page **uncached**. If you want the reverse proxy and the cache pre-loading instead, use the [cached variant](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/templates/website/usage_scenario_cached.yml) as your starting point. + +Once you got this quick measurement running iterate on it by extending the file with more steps, for instance measuring all the sub-pages on your domain Bonus tip: If you apply `--quick` to the `run-template.sh` call the measurement is quicker for debugging purposes. However results will be not as reliable. Use only for debugging! @@ -42,16 +44,20 @@ The Green Metrics Tool supports **Playwright** as a first-class command type in ### Simplified Setup with GMT Helper -Getting started with Playwright is easy using the `!include-gmt-helper`. By including `gmt-playwright-v1.0.0.yml`, the Green Metrics Tool automatically: +Getting started with Playwright is easy using the `!include-gmt-helper` tag. By including `gmt-playwright.yml`, the Green Metrics Tool automatically: 1. Configures the Playwright service container (`gmt-playwright-nodejs`) with the official Microsoft Playwright image. 2. Installs all necessary Playwright libraries. 3. Starts the Playwright browser and an IPC listener in the background. -To get started, add the following to your `usage_scenario.yml`: +Note that the helper is a YAML **tag on the `compose-file` value** — it is separated by a space and takes no colon. A minimal `usage_scenario.yml` looks like this: ```yaml -!include-gmt-helper: gmt-playwright-v1.0.0.yml +name: "My website measurement" +author: "A wizard" +description: "Measures the home page of green-coding.io" + +compose-file: !include-gmt-helper gmt-playwright.yml # Your flow can now use the gmt-playwright-nodejs container flow: @@ -85,12 +91,23 @@ This allows you to inline browser interactions alongside other commands for fine ### Caching with a Reverse Proxy -For scenarios where you want to cache browser requests to minimize network variability, use the `gmt-playwright-with-cache-v1.0.0.yml` helper. It sets up an additional `squid` reverse proxy service and configures Playwright to use it. +For scenarios where you want to cache browser requests to minimize network variability, use the `gmt-playwright-with-cache.yml` helper. It sets up an additional `squid` reverse proxy service and configures Playwright to use it. ```yaml -!include-gmt-helper: gmt-playwright-with-cache-v1.0.0.yml +name: "My cached website measurement" +author: "A wizard" +description: "Measures the home page of green-coding.io through a caching reverse proxy" + +compose-file: !include-gmt-helper gmt-playwright-with-cache.yml flow: + - name: "Warmup and Caching" + container: gmt-playwright-nodejs + hidden: true + commands: + - type: playwright + command: await gmtPlaywrightCache("https://green-coding.io", 5); + - name: "Go to home page with cache" container: gmt-playwright-nodejs commands: @@ -98,6 +115,8 @@ flow: command: await page.goto("https://green-coding.io") ``` +The `gmtPlaywrightCache(url, sleep)` helper pre-loads the full page once so that the following steps are served from the proxy cache. Compare [`usage_scenario_cached.yml`](https://github.com/green-coding-solutions/green-metrics-tool/blob/main/templates/website/usage_scenario_cached.yml) for a complete working example. + --- ### Full Example @@ -105,11 +124,12 @@ flow: Here is a complete `usage_scenario.yml` that measures the homepage of `green-coding.io`: ```yaml -!include-gmt-helper: gmt-playwright-v1.0.0.yml - name: "Measure homepage of green-coding.io" +author: "A wizard" description: "A simple example that measures the energy consumption of a website's homepage." +compose-file: !include-gmt-helper gmt-playwright.yml + flow: - name: "Navigate to green-coding.io" container: gmt-playwright-nodejs @@ -125,7 +145,7 @@ flow: container: gmt-playwright-nodejs commands: - type: playwright - command: await page.screenshot({ path: '/tmp/repo/screenshot.png' }) + command: 'await page.screenshot({ path: "/tmp/repo/screenshot.png" })' note: "Take a screenshot to verify the page loaded" ``` diff --git a/content/en/docs/measuring/metric-providers/atx-energy-dc-channel.md b/content/en/docs/measuring/metric-providers/atx-energy-dc-channel.md index 7a3d3fb..0a24485 100644 --- a/content/en/docs/measuring/metric-providers/atx-energy-dc-channel.md +++ b/content/en/docs/measuring/metric-providers/atx-energy-dc-channel.md @@ -8,7 +8,7 @@ weight: 100 --- {{< callout context="caution" icon="outline/alert-triangle" >}} -This is a legacy provider and is not maintained anymore. It is only used in an old version of the Green Metrics Tool! +This provider does not ship with the Green Metrics Tool anymore and this page is only kept as a reference for old versions. The importer script `tools/dc_converter.py` described below does however still exist in the repository. {{< /callout >}} ## What it does @@ -40,7 +40,7 @@ The script will detect the measurement resolution automatically though if you al ### Example call ```bash -python3 tools/dc_converter.py filename project_id db_host db_pw +python3 tools/dc_converter.py filename run_id db_host db_pw ``` ### Software diff --git a/content/en/docs/measuring/metric-providers/carbon-intensity-electricitymaps-machine.md b/content/en/docs/measuring/metric-providers/carbon-intensity-electricitymaps-machine.md index e1c5c92..3253dc5 100644 --- a/content/en/docs/measuring/metric-providers/carbon-intensity-electricitymaps-machine.md +++ b/content/en/docs/measuring/metric-providers/carbon-intensity-electricitymaps-machine.md @@ -53,7 +53,7 @@ The provider must be configured in the `config.yml`: ```yml measurement: - metric-providers: + metric_providers: common: carbon_intensity_electricitymaps_machine: region: 'DE' @@ -84,8 +84,8 @@ Each row consists of: - `value`: The carbon intensity at that point in time in `gCO2e/kWh` as an integer. - `detail_name`: Always `electricity_maps` to indicate the data source. -Any errors that occur while talking to the API are appended to the provider's stderr buffer and can -be inspected in the run details in the frontend. +The provider does not have a stderr buffer. Any error that occurs while talking to the API is +raised as an exception and aborts the run. ### How it works @@ -124,7 +124,7 @@ underlying exception. this provider will not work. Use the [Elephant carbon intensity provider]({{< relref "carbon-intensity-elephant-machine" >}}) in that case, which can be hosted locally. - The free Electricity Maps token is rate-limited. If you run a large number of measurements you - may hit the limit and the provider will record an error and skip data for that run. + may hit the limit, in which case the provider raises an error and the run fails. - The smallest temporal granularity supported by this provider is 5 minutes. Short-running benchmarks (under a few minutes) will usually have only a single carbon intensity value associated with them. diff --git a/content/en/docs/measuring/metric-providers/carbon-intensity-elephant-machine.md b/content/en/docs/measuring/metric-providers/carbon-intensity-elephant-machine.md index ffbb880..953aefb 100644 --- a/content/en/docs/measuring/metric-providers/carbon-intensity-elephant-machine.md +++ b/content/en/docs/measuring/metric-providers/carbon-intensity-elephant-machine.md @@ -44,7 +44,7 @@ The provider must be configured in the `config.yml`: ```yml measurement: - metric-providers: + metric_providers: common: carbon_intensity_elephant_machine: region: 'DE' @@ -83,8 +83,8 @@ Each row consists of: - `detail_name`: The name of the Elephant carbon provider that produced the value (e.g. `bundesnetzagentur_de`). For carbon simulation runs this is the simulation UUID. -Any errors that occur while talking to the Elephant service are appended to the provider's stderr -buffer and can be inspected in the run details in the frontend. +The provider does not have a stderr buffer. Any error that occurs while talking to the Elephant +service is raised as an exception and aborts the run. ### How it works @@ -95,8 +95,7 @@ are read at the end of the run it issues a single HTTP GET request to ://:/carbon-intensity/history ``` -with the configured `region`, the start/end times of the run, the `provider` filter, and -`update=true` so that Elephant re-fetches stale data from its upstream sources before responding. +with the configured `region`, the start/end times of the run and the `provider` filter. The response is a list of `{time, carbon_intensity, provider}` entries which are sorted, rounded to integer values and expanded to the configured `sampling_rate`. diff --git a/content/en/docs/measuring/metric-providers/carbon-intensity-level-electricitymaps-machine.md b/content/en/docs/measuring/metric-providers/carbon-intensity-level-electricitymaps-machine.md new file mode 100644 index 0000000..8efbe4c --- /dev/null +++ b/content/en/docs/measuring/metric-providers/carbon-intensity-level-electricitymaps-machine.md @@ -0,0 +1,154 @@ +--- +title: "Carbon Intensity Level - Electricity Maps - Machine" +description: "Documentation of CarbonIntensityLevelElectricitymapsMachineProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 223 +--- + +### What it does + +This provider fetches the current carbon intensity **level** of the electricity grid for a +configured region from the [Electricity Maps API](https://www.electricitymaps.com/) and stores it +as a metric of the run. + +A level is a coarse classification (`low`, `moderate`, `high`) rather than a number in gCO2e/kWh. +If you want the actual carbon intensity of the grid, use the +[Carbon Intensity Electricity Maps provider]({{< relref "carbon-intensity-electricitymaps-machine" >}}) +instead. This provider is useful when you want to know *whether the grid was clean or dirty* while +a run happened, for instance to schedule workloads, and not to compute an emissions figure. + +### Classname + +- `CarbonIntensityLevelElectricitymapsMachineProvider` + +### Metric Name + +- `carbon_intensity_level_electricitymaps_machine` + +### Unit + +- `level` + +The API returns a string, which is mapped to an integer before being stored: + +| API level | Stored value | +|------------|--------------| +| `low` | `1` | +| `moderate` | `2` | +| `high` | `3` | + +The comparison is case-insensitive and whitespace is stripped. Any other level raises an error — +the provider does not guess. + +### Prerequisites & Installation + +The provider is a pure Python provider and does not need any binary to be compiled. It does however +require network access from the measurement machine to `api.electricitymaps.com` and a valid +Electricity Maps API token. + +You can obtain a free token (subject to fair-use limits) at +[https://api-portal.electricitymaps.com/](https://api-portal.electricitymaps.com/). + +Please note: The free token is for non-commercial use only. If you want to use Electricity Maps +data in a commercial context you need to acquire a commercial license from Electricity Maps. + +### Configuration + +The provider lives in the `common` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + common: + carbon_intensity_level_electricitymaps_machine: + region: 'DE' + token: 'XXXX' + sampling_rate: 99 # Remove if you don't want value padding +``` + +Config keys: + +- `region` — **required**. The Electricity Maps zone identifier (e.g. `DE`, `FR`, `US-CAL-CISO`). A + list of available zones can be found in the + [Electricity Maps API documentation](https://portal.electricitymaps.com/docs/getting-started#geographical-coverage). + Without a region the provider refuses to start. +- `token` — **required**. A valid Electricity Maps API token. Without a token the provider refuses + to start. +- `sampling_rate` — optional, in milliseconds. Defaults to `-1`. This value is not used to call the + API more frequently (the API is only called once per run) but to *pad* the returned value to the + same resolution as the other metric providers so that the time series can be joined cleanly. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +This is a pure Python provider. There is no binary and no command line interface. + +### Output + +The provider does not produce a continuous Stdout stream like the C-based providers. The data is +fetched once per run from the Electricity Maps API and inserted directly into the database as a +metric of the run. Its stderr is always empty. + +Each row consists of: + +- `time`: The timestamp of the data point in microseconds (UNIX epoch). +- `value`: The level as an integer — `1`, `2` or `3` per the mapping above. +- `detail_name`: Always `electricity_maps` to indicate the data source. + +### How it works + +On `start_profiling` and `stop_profiling` the provider records UTC timestamps. When the metrics are +read at the end of the run it issues a single HTTP GET request to + +```text +https://api.electricitymaps.com/v4/carbon-intensity-level/latest +``` + +with the configured zone as the `zone` query parameter and the token in the `auth-token` header. +The `level` of the first entry of the response's `data` array is mapped to an integer. + +That single value is then emitted twice — once at the start timestamp and once at the end timestamp +of the run — and expanded to the configured `sampling_rate`. If the two timestamps are identical +the end timestamp is nudged forward by one microsecond so the rows remain distinct. If +`sampling_rate` is `-1` or otherwise not positive, only the two boundary records are stored. + +### Health check + +When the provider starts, it issues a request against the same `latest` endpoint to confirm that +the configured zone is valid and that the API token is accepted. If the API returns `401` or `403` +the provider raises a `MetricProviderConfigurationError` with a hint that the token is incorrect. +If the endpoint cannot be reached at all (DNS/network issues) the same error is raised with the +underlying exception. + +### Caveats + +- The endpoint is `latest`, and it is only queried **after** the run has finished. The stored level + is therefore the level at the time the metrics were read, not a level measured across the + measurement window. For short runs these are effectively the same; for long runs the level may + have changed during the run without that being visible. +- Both stored data points carry the same value. The series is flat by construction — this provider + cannot show a level changing during a run. +- The value is an ordinal classification, not a physical quantity. `high` being `3` and `low` being + `1` does not mean `high` is three times `low`. Do not average, sum or multiply these values. +- The provider requires network access during the run. If the measurement machine is air-gapped + this provider will not work. +- The free Electricity Maps token is rate-limited. Note that this provider calls the API twice per + run: once for the health check at startup and once when reading the metrics. +- Not every zone supports the carbon intensity level endpoint. + +### Troubleshooting + +- **`Please set the region config option ...`** / **`Please set the token config option ...`** — the + provider is enabled but `region` or `token` is missing from the `config.yml`. +- **`Electricity Maps token was rejected. Please verify the token in the config.yml`** — the API + answered `401` or `403`. Check the token at + [https://api-portal.electricitymaps.com/](https://api-portal.electricitymaps.com/). +- **`Electricity Maps base URL ... could not be reached`** — check the network connectivity of the + measurement machine and that no firewall blocks `api.electricitymaps.com`. +- **`Unknown carbon intensity level '' from Electricity Maps`** — the API returned a level + outside `low` / `moderate` / `high`. +- **`'data' array missing or empty`** / **`'level' key missing`** — the API responded, but not with + a level for this zone. Verify that the zone identifier is correct and supported. diff --git a/content/en/docs/measuring/metric-providers/carbon-intensity-static-machine.md b/content/en/docs/measuring/metric-providers/carbon-intensity-static-machine.md new file mode 100644 index 0000000..5ddc751 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/carbon-intensity-static-machine.md @@ -0,0 +1,125 @@ +--- +title: "Carbon Intensity - Static - Machine" +description: "Documentation of CarbonIntensityStaticMachineProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 222 +--- + +### What it does + +This provider supplies a **fixed** grid carbon intensity value that you configure yourself. It does +not talk to any external service. + +It is the direct replacement for the former static `sci.I` value in the `config.yml`. Carbon +intensity is no longer an SCI configuration value but a metric provider, so that you can choose +between a static value and live grid data per run. See +[Grid Carbon Intensity →]({{< relref "/docs/measuring/carbon/grid-carbon-intensity" >}}) for the +background of that migration and for the alternatives. + +Use this provider when you want **reproducible measurements** and **fair comparisons**: every run +on the machine uses the same baseline, so a change in reported carbon can only come from a change +in the software, never from a change in the grid. + +This is the **only carbon intensity provider that is enabled by default** in +`config.yml.example`, with a value of `445` gCO2e/kWh — the global average for 2024 according to +the [IEA](https://www.iea.org/reports/electricity-2025/emissions). + +### Classname + +- `CarbonIntensityStaticMachineProvider` + +### Metric Name + +- `carbon_intensity_static_machine` + +### Unit + +- `gCO2e/kWh` + +The provider stores integer values. The configured value may be a float and is rounded to the +nearest integer before being persisted. + +### Configuration + +The provider lives in the `common` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + common: + carbon_intensity_static_machine: + # Static carbon intensity in gCO2e/kWh. Replaces the former SCI 'I' value. + value: 445 + sampling_rate: 99 +``` + +Config keys: + +- `value` — **required**. The static carbon intensity in gCO2e/kWh. Must be numeric. If it is + missing the provider raises a `MetricProviderConfigurationError` at startup, and so does a value + that cannot be parsed as a number. +- `sampling_rate` — optional, in milliseconds. Defaults to `-1`. This does not make the provider + measure anything more often — there is nothing to poll — but it *pads* the value to the same + resolution as the other providers so the time series can be joined cleanly. Remove it if you do + not want value padding. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +This is a pure Python provider. There is no binary and no command line interface. + +### Output + +The provider does not produce a continuous Stdout stream like the C-based providers. The value is +generated in memory at the end of the run and inserted directly into the database as a metric of +the run. Its stderr is always empty. + +Each row consists of: + +- `time`: The timestamp of the data point in microseconds (UNIX epoch). +- `value`: The configured carbon intensity as an integer. +- `detail_name`: Always `static` to indicate the data source. + +### How it works + +On `start_profiling` and `stop_profiling` the provider records UTC timestamps. Nothing runs in +between — there is no subprocess and no polling. + +When the metrics are read at the end of the run, it emits two records with the configured value: +one at the start timestamp and one at the end timestamp. If the two timestamps are identical +(a run so short that both fall in the same microsecond) the end timestamp is nudged forward by one +microsecond so the two rows remain distinct. + +Those two records are then expanded to the configured `sampling_rate`, producing a value on every +sampling grid point between start and end. If `sampling_rate` is `-1` or otherwise not positive, +the expansion is skipped and only the two boundary records are stored. + +### Health check + +The provider overrides the system check to always succeed. There is no external system to verify +for a statically configured value, and no check for a parallel instance is performed. + +### Caveats + +- This is a **configured constant, not a measurement**. It says nothing about the actual carbon + intensity of the grid during the run. That is the point of the provider — reproducibility — but + it means the reported operational carbon is only as meaningful as the value you chose. +- The default of `445` is a global average. If you want a value representative of your own grid, + set it to your region's figure, or use one of the live providers such as + [Electricity Maps]({{< relref "carbon-intensity-electricitymaps-machine" >}}) or + [Elephant]({{< relref "carbon-intensity-elephant-machine" >}}). +- The value is rounded to an integer. Sub-1 gCO2e/kWh precision is not preserved. +- Do not enable more than one carbon intensity provider at a time unless you deliberately want + multiple, differently-sourced carbon intensity series on the same run. + +### Troubleshooting + +- **`Please set the value config option for CarbonIntensityStaticMachineProvider in the config.yml`** — + the provider is enabled but has no `value` key. +- **`value for CarbonIntensityStaticMachineProvider must be numeric (got ...)`** — the `value` key + is not a number. Quoted strings such as `'445 gCO2e/kWh'` will trigger this. +- **`... provider did not record start/end times`** — the provider was read without a complete + start/stop cycle. This indicates an aborted run rather than a configuration problem. diff --git a/content/en/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component.md b/content/en/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component.md index 88c56ae..c843d4f 100644 --- a/content/en/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component.md +++ b/content/en/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component.md @@ -9,7 +9,7 @@ weight: 110 ### What it does -This metric provider reads the energy of the CPU Package from the Running Average Power Limit (RAPL) interface via a machine specific register (MSR) that is present on most modern Intel processors. In depth information about RAPL can be found in the [Intel Software Developer Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +This metric provider reads the energy of the CPU Package from the Running Average Power Limit (RAPL) interface via a machine specific register (MSR) that is present on most modern Intel and AMD processors. In depth information about RAPL can be found in the [Intel Software Developer Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). This MSR keeps a running count of the energy used in a specified domain in microJoules. This metric provider specifically reads from the `energy-pkg` domain, which gives you the cumulatove energy used by the domains `energy-cores`, `energy-gpu` and some extra parts like the voltage regulator and such that also reside on the package. @@ -65,10 +65,12 @@ Any errors are printed to Stderr. We use a modified version of the open source code found here: ([github](https://github.com/deater/uarch-configure/blob/master/rapl-read/rapl-read.c)) -First we check if the CPU is compatible by reading the cpu info from `/proc/cpuinfo` and checking against the following list of supported CPUs: +First we check if the CPU is compatible by reading the cpu info from `/proc/cpuinfo`. Supported are Intel CPUs of family 6 and AMD CPUs of family 17h / 19h. On AMD the RAPL MSRs live at different addresses, which the provider selects automatically. + +The following CPU models are known to the provider: ```txt -CPU_SANDYBRIDGE, CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_BROADWELL_DE, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_SILVERMONT, CPU_ATOM_AIRMONT, CPU_ATOM_MERRIFIELD, CPU_ATOM_MOOREFIELD, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_TIGER_LAKE +CPU_SANDYBRIDGE, CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_BROADWELL_DE, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_SILVERMONT, CPU_ATOM_AIRMONT, CPU_ATOM_MERRIFIELD, CPU_ATOM_MOOREFIELD, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_ATOM_DENVERTON, CPU_TIGER_LAKE, CPU_AMD_FAM17H ``` It reads the values from `/dev/cpu/%d/msr` diff --git a/content/en/docs/measuring/metric-providers/cpu-energy-rapl-scaphandre-component.md b/content/en/docs/measuring/metric-providers/cpu-energy-rapl-scaphandre-component.md new file mode 100644 index 0000000..4a1804e --- /dev/null +++ b/content/en/docs/measuring/metric-providers/cpu-energy-rapl-scaphandre-component.md @@ -0,0 +1,159 @@ +--- +title: "CPU Energy - RAPL - Scaphandre - component" +description: "Documentation of CpuEnergyRaplScaphandreComponentProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 111 +--- + +### What it does + +This metric provider reads the Intel/AMD RAPL energy counters on **Windows** through the +[ScaphandreDrv](https://github.com/hubblo-org/scaphandre) kernel driver. It is the Windows +counterpart to the Linux [CPU Energy RAPL MSR provider]({{< relref "cpu-energy-RAPL-MSR-component" >}}). + +### Classname + +- `CpuEnergyRaplScaphandreComponentProvider` + +### Metric Name + +- `cpu_energy_rapl_msr_component` + +Please note that the metric name is **not** `cpu_energy_rapl_scaphandre_component`. The provider +deliberately registers itself under the same metric name as the Linux MSR provider so that runs +made on Windows and on Linux carry the same metric and can be compared directly. + +The name you use in the `config.yml` (`cpu_energy_rapl_scaphandre_component`) is therefore +different from the metric name that ends up in the database (`cpu_energy_rapl_msr_component`). + +### Unit + +- `uJ` + +### Configuration + +The provider lives in the `windows` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + windows: + cpu_energy_rapl_scaphandre_component: + sampling_rate: 99 + # Optionally disable individual RAPL domains + # domains: + # cpu_gpu: False + # dram: False +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to the binary as `-i`. +- `domains` — optional map of RAPL domains to booleans. Valid keys are `cpu_package`, `cpu_cores`, + `cpu_gpu`, `dram` and `psys`. Any domain set to a falsy value is passed to the binary via `-x` + and is never read. Setting a domain to `True` has no effect beyond not disabling it, since all + supported domains are measured by default. An unknown domain name raises a + `MetricProviderConfigurationError` at startup. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +- args + - `-i`: interval in milliseconds (the binary's own default is 99) + - `-d`: measure a single named domain only and skip auto-detection + - `-x`: comma-separated list of domains to disable, e.g. `-x cpu_gpu,dram` + - `-c`: check mode — reads the RAPL power unit MSR and exits + +The provider itself only ever passes `-i` and (when `domains` disables something) `-x`. + +```bash +metric-provider-binary.exe -i 99 -x cpu_gpu,dram +``` + +### Output + +This metric provider prints to *Stdout* a continuous stream of data. The format of the data is as follows: + +`TIMESTAMP READING DETAIL_NAME` + +Where: + +- `TIMESTAMP`: Unix timestamp, in microseconds +- `READING`: The energy consumed by the domain since the previous sample in *uJ* +- `DETAIL_NAME`: The RAPL domain — one of `cpu_package`, `cpu_cores`, `cpu_gpu`, `dram`, `psys` + +Any errors are printed to Stderr. + +Unlike the other providers, the Python side does not redirect Stdout through a shell. It opens the +log file itself and hands the file handle to the subprocess. + +### How it works + +The provider is a C binary (`metric-provider-binary.exe`) that opens the driver device +`\\.\ScaphandreDriver` and issues `IOCTL_READ_MSR` calls to read the RAPL MSRs directly. It reads +CPU index 0 only. + +The energy unit is derived from `MSR_RAPL_POWER_UNIT` (`0x606`), with a fallback to the AMD +register `0xC0010299`. Each domain is then read from its own energy status register and the +delta to the previous sample is converted to microjoules. A negative delta is treated as a 32-bit +counter wrap and corrected by adding the counter range. + +At startup the binary auto-detects which domains are actually active by taking one sample 100 ms +apart per domain: `dram`, `cpu_gpu` and `psys` are dropped if they report no energy progression. +Auto-detection is skipped entirely when a single domain was forced with `-d`, and domains excluded +via `-x` are removed before detection so they are never probed. + +Timing uses `QueryPerformanceCounter` plus a wall-clock offset taken at startup, mirroring the +`get_time_offset()` / `get_adjusted_time()` approach of the Linux providers. The binary calls +`timeBeginPeriod(1)` to raise the Windows timer resolution to 1 ms, because the default 15.6 ms +timer granularity would make `Sleep(99)` overshoot far outside the tool's sampling rate tolerance. +The main loop is deadline-based: it records the tick at the start of each iteration and sleeps only +the *remaining* time, so measurement overhead does not accumulate into drift. + +The `cpu_package` domain doubles as a health canary. If its read fails, the driver is considered +faulty. After 5 consecutive failures the binary exits with code 2 so that the tool notices the +process died rather than silently recording nothing. If you disable `cpu_package` via `domains`, +it is still read internally as the canary but is not printed. + +### Installation + +The binary is compiled with MSVC. From the *x64 Native Tools Command Prompt for VS*, run +`build.bat` in the provider folder, which invokes: + +```bash +cl rapl_reader_cli.c /Fe:metric-provider-binary /O2 /W3 /link winmm.lib +``` + +`winmm.lib` is required for `timeBeginPeriod` / `timeEndPeriod`. + +The ScaphandreDrv kernel driver must be installed and running before the provider can be used. + +### Caveats + +- The metric name in the database is `cpu_energy_rapl_msr_component`, not the config key. See + [Metric Name](#metric-name) above. +- Only CPU index 0 is read. On multi-socket machines the other packages are not measured. +- The `cpu_gpu` domain reports a minimum of 2 uJ when the real delta is 0. This is done to avoid a + resolution underflow error while keeping the time series gap-free, so a constant 2 uJ on + `cpu_gpu` should be read as "no measurable GPU energy", not as an actual measurement. +- Domains that are inactive at startup are dropped for the whole run. A domain that only becomes + active later will not appear. +- RAPL is an on-chip model, not a physical power meter at the wall. See the + [RAPL documentation]({{< relref "cpu-energy-RAPL-MSR-component" >}}) for the general caveats + that apply to all RAPL-based providers. + +### Troubleshooting + +- **`Cannot open driver. Error: `** — the ScaphandreDrv driver is not installed or not running. + Check with `sc.exe query ScaphandreDrv` and start it with `sc.exe start ScaphandreDrv`. +- **`Cannot read RAPL power unit MSR.`** — the driver responds but the CPU does not expose the RAPL + power unit register. This typically means RAPL is unavailable, for instance in a VM. +- **`Fatal: ScaphandreDrv driver lost after 5 consecutive failures.`** — the driver stopped + responding during the measurement. Verify it is still running with `sc.exe query ScaphandreDrv`. +- **`Unknown RAPL domain ''`** — a `domains` key in the `config.yml` is misspelled. Valid + values are `cpu_package`, `cpu_cores`, `cpu_gpu`, `dram` and `psys`. +- If the system check fails, make sure that `metric-provider-binary.exe` exists in the provider + folder and that the driver is installed and running. diff --git a/content/en/docs/measuring/metric-providers/cpu-frequency-msr-core.md b/content/en/docs/measuring/metric-providers/cpu-frequency-msr-core.md index fa769df..d74833f 100644 --- a/content/en/docs/measuring/metric-providers/cpu-frequency-msr-core.md +++ b/content/en/docs/measuring/metric-providers/cpu-frequency-msr-core.md @@ -9,7 +9,7 @@ weight: 120 ### What it does -This metric provider measures the actual CPU frequency for every core on **Intel CPUs** by reading +This metric provider measures the actual CPU frequency for every core on **x86 CPUs** by reading the hardware APERF and MPERF performance counters via the Linux MSR (Model Specific Register) interface. ### Classname @@ -88,8 +88,8 @@ binary is installed with the setuid-root bit set. core-to-core. - For most users the per-core detail will be noise rather than actionable data. We recommend looking at the aggregate or only enabling this provider when debugging frequency-related behaviour. -- This provider only works on **Intel CPUs**. The APERF/MPERF MSRs are Intel-specific and are not - available on AMD or ARM processors. +- This provider only works on **x86 CPUs**. The APERF/MPERF MSRs are architectural on both Intel and + AMD, but are not available on ARM processors. - It cannot be used on most VMs or in containers where MSR access is blocked. ### Troubleshooting diff --git a/content/en/docs/measuring/metric-providers/cpu-throttling-msr-component.md b/content/en/docs/measuring/metric-providers/cpu-throttling-msr-component.md new file mode 100644 index 0000000..6644d51 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/cpu-throttling-msr-component.md @@ -0,0 +1,131 @@ +--- +title: "CPU Throttling - MSR - component" +description: "Documentation of CpuThrottlingMsrComponentProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 121 +--- + +### What it does + +This metric provider reports whether each CPU package is currently being throttled, by reading the +`IA32_THERM_STATUS` register on **Intel CPUs** via the Linux MSR (Model Specific Register) +interface. It distinguishes two independent causes: thermal throttling and power limit throttling. + +It is a debugging and introspection provider. It tells you *why* a measurement may be slower or +less reproducible than expected — it does not measure energy. + +### Classname + +- `CpuThrottlingMsrComponentProvider` + +### Metric Name + +The provider registers itself as `cpu_throttling_msr_component`, but it splits its readings into +two sub-metrics, and these are what actually land in the database: + +- `cpu_throttling_thermal_msr_component` +- `cpu_throttling_power_msr_component` + +### Unit + +- `boolean` + +The value is `1` while the corresponding throttling condition is signalled and `0` otherwise. + +### Configuration + +The provider lives in the `linux` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + linux: + cpu_throttling_msr_component: + sampling_rate: 99 +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to the binary as `-i`. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +- args + - `-i`: interval in milliseconds + - `-c`: check/test mode — opens the MSR of CPU 0, reads `IA32_THERM_STATUS` and exits + - `-h`: prints usage and exits + +By default the measurement interval is 1000 ms. + +```bash +./metric-provider-binary -i 100 +``` + +### Output + +This metric provider prints to *Stdout* a continuous stream of data. The format of the data is as follows: + +`TIMESTAMP THERMAL_THROTTLING_STATUS POWER_LIMIT_THROTTLING_STATUS PACKAGE` + +Where: + +- `TIMESTAMP`: Unix timestamp, in microseconds +- `THERMAL_THROTTLING_STATUS`: `1` if the thermal throttling bit is set, `0` otherwise +- `POWER_LIMIT_THROTTLING_STATUS`: `1` if the power limit bit is set, `0` otherwise +- `PACKAGE`: The package identifier, formatted as `Package_` + +The package identifier becomes the `detail_name` of both sub-metrics. + +Any errors are printed to Stderr. + +### How it works + +The provider is a compiled C binary that reads the `IA32_THERM_STATUS` register (MSR `0x19C`) once +per package per interval and extracts two bits: + +- Bit 0 (`THERMAL_THROTTLING_STATUS_BIT`) — thermal throttling +- Bit 10 (`POWER_LIMIT_STATUS_BIT`) — power limit throttling + +Package discovery happens at startup by enumerating +`/sys/devices/system/cpu/cpuX/topology/physical_package_id` and recording the first CPU seen for +each distinct package id. Offline CPUs and non-contiguous numbering are skipped. Up to 1024 CPUs +and 16 packages are supported; a higher package id aborts the binary. If no packages are detected +at all the binary exits with code 1. + +The MSR of the first CPU of each package is then opened via `/dev/cpu//msr` and read in a loop. + +Because the binary needs to open `/dev/cpu/*/msr` (which is restricted to root), the compiled +binary is installed with the setuid-root bit set. + +The two bits are read from a single register read, so a row always carries a consistent pair. +On the Python side the dataframe is split into the two sub-metrics listed above, each keeping the +package as its `detail_name`. + +### Caveats + +- The register is sampled at the configured interval, so throttling that starts and stops entirely + between two samples is not recorded. A `0` therefore means "not throttling at the sampling + instant", not "never throttled". +- Only the first CPU of each package is read. The value is a package-level signal, not per-core. +- This provider only works on **Intel CPUs**. `IA32_THERM_STATUS` is Intel-specific. +- It cannot be used on most VMs or in containers where MSR access is blocked. +- The unit is `boolean`, so the usual aggregations (sum, average) over these values are not + energy-meaningful. Read the series as a timeline, not as a total. + +### Troubleshooting + +The provider requires read access to `/dev/cpu/*/msr`. Common failure modes: + +- **`rdmsr: No CPU `** — the MSR device for that CPU does not exist. +- **`rdmsr: CPU doesn't support MSRs`** — the `msr` kernel module is not loaded. Run + `sudo modprobe msr`. +- **`rdmsr:open: Permission denied`** — the setuid bit is not set on the binary. Re-run `make` from + the provider directory (requires sudo). +- **`No CPU packages detected`** — `/sys/devices/system/cpu/cpu*/topology/physical_package_id` + could not be read. This usually indicates a VM or a restricted container. +- **`Package ID exceeds maximum supported packages (16)`** — the machine reports more packages + than the binary supports. diff --git a/content/en/docs/measuring/metric-providers/cpu-time-cgroup-container.md b/content/en/docs/measuring/metric-providers/cpu-time-cgroup-container.md index aa17ab2..e35db76 100644 --- a/content/en/docs/measuring/metric-providers/cpu-time-cgroup-container.md +++ b/content/en/docs/measuring/metric-providers/cpu-time-cgroup-container.md @@ -17,7 +17,7 @@ This metric provider reads time spent in the CPU based on the cgroups stats file ### Metric Name -- `cpu_time-cgroup_container` +- `cpu_time_cgroup_container` ### Input Parameters @@ -25,7 +25,7 @@ This metric provider reads time spent in the CPU based on the cgroups stats file - `-s`: container-ids separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s 7f38a4c25fb8f9d5f8651d6ed986b3658dba20d1f5fec98a1f71c141c2b48f4b,c3592e1385d63f9c7810470b12aa00f7d6f7c0e2b9981ac2bdb4371126a0660a diff --git a/content/en/docs/measuring/metric-providers/cpu-time-cgroup-system.md b/content/en/docs/measuring/metric-providers/cpu-time-cgroup-system.md index 7c9bfd7..b7d6506 100644 --- a/content/en/docs/measuring/metric-providers/cpu-time-cgroup-system.md +++ b/content/en/docs/measuring/metric-providers/cpu-time-cgroup-system.md @@ -32,7 +32,7 @@ Unlike the other cgroup system metric providers, this metric provider does not c - args - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 diff --git a/content/en/docs/measuring/metric-providers/cpu-time-procfs-system.md b/content/en/docs/measuring/metric-providers/cpu-time-procfs-system.md index a1d5ebc..dcdd405 100644 --- a/content/en/docs/measuring/metric-providers/cpu-time-procfs-system.md +++ b/content/en/docs/measuring/metric-providers/cpu-time-procfs-system.md @@ -24,7 +24,7 @@ This metric provider reads the total time spent in the CPU based on the system ` - args - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 diff --git a/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-container.md b/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-container.md index 0cf0331..84267b6 100644 --- a/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-container.md +++ b/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-container.md @@ -24,7 +24,7 @@ This metric provider calculates an estimate of the % total CPU usage based on th - `-s`: container-ids separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s 7f38a4c25fb8f9d5f8651d6ed986b3658dba20d1f5fec98a1f71c141c2b48f4b,c3592e1385d63f9c7810470b12aa00f7d6f7c0e2b9981ac2bdb4371126a0660a @@ -39,7 +39,7 @@ This metric provider prints to Stdout a continuous stream of data. The format of Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The estimated % CPU used +- `READING`: The estimated % CPU used. The unit is a *Ratio*, so the value is multiplied with 10000 to be expressed as an integer - `CONTAINER-ID`: The container ID that this reading is for Any errors are printed to Stderr. @@ -54,7 +54,7 @@ The provider reads from two files. To get the number of microseconds spent in th /sys/fs/cgroup/user.slice/user-.slice/user@.service/user.slice/docker-.scope/cpu.stat ``` -To get the total time spent by the cpu during that time interval, in Jiffies, you read from `/proc/stat`. We collect **user**, **nice**, **system**, **idle** **iowait**, **irq**, **softirq**, **steal** (see definitions in [CPU stats documentation](https://www.idnt.net/en-US/kb/941772)), add them together, divide by _SC_CLK_TCK_ (typically 100 Hz). The percentage of the cgroup time divided by this sum is the total percentage of CPU time spent by the container. +To get the total time spent by the cpu during that time interval, in Jiffies, you read from `/proc/stat`. We collect **user**, **nice**, **system**, **idle** **iowait**, **irq**, **softirq** (see definitions in [CPU stats documentation](https://www.idnt.net/en-US/kb/941772)), add them together, divide by `_SC_CLK_TCK` (typically 100 Hz). The percentage of the cgroup time divided by this sum is the total percentage of CPU time spent by the container. **steal** is deliberately not collected, as it is time spent outside of the measured system. Then it calculates the % cpu used via this formula: `container_reading * 10000 / main_cpu_reading` diff --git a/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-system.md b/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-system.md index d3d9b41..921c6c4 100644 --- a/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-system.md +++ b/content/en/docs/measuring/metric-providers/cpu-utilization-cgroup-system.md @@ -27,7 +27,7 @@ It can be used for system monitoring and tracking background processes such as t - `-s`: cgroup name strings separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s org.gnome.Shell@wayland.service,session-2.scope @@ -42,7 +42,7 @@ This metric provider prints to Stdout a continuous stream of data. The format of Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The estimated % CPU used +- `READING`: The estimated % CPU used. The unit is a *Ratio*, so the value is multiplied with 10000 to be expressed as an integer - `CGROUP-NAME`: The cgroup name that this reading is for Any errors are printed to Stderr. diff --git a/content/en/docs/measuring/metric-providers/cpu-utilization-mach-system.md b/content/en/docs/measuring/metric-providers/cpu-utilization-mach-system.md new file mode 100644 index 0000000..fc72a5f --- /dev/null +++ b/content/en/docs/measuring/metric-providers/cpu-utilization-mach-system.md @@ -0,0 +1,120 @@ +--- +title: "CPU % - mach - system" +description: "Documentation of CpuUtilizationMachSystemProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 143 +--- + +### What it does + +This metric provider measures the total CPU utilization of the system on **macOS** by reading the +per-CPU load counters from the Mach kernel via `host_processor_info()`. + +It is the macOS equivalent of the +[CPU % procfs system provider]({{< relref "cpu-utilization-procfs-system" >}}). + +### Classname + +- `CpuUtilizationMachSystemProvider` + +### Metric Name + +- `cpu_utilization_mach_system` + +### Unit + +- `Ratio` + +Since we want the output as a ratio that can be expressed as an integer, the percentage is +multiplied by 100. A reading of `4250` therefore means 42.50 % CPU utilization. + +### Configuration + +The provider lives in the `macos` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + macos: + cpu_utilization_mach_system: + sampling_rate: 99 +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to the binary as `-i`. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +- args + - `-i`: interval in milliseconds + - `-c`: check/test mode — queries the CPU info once and exits + - `-h`: prints usage and exits + +By default the measurement interval is 1000 ms. + +```bash +./metric-provider-binary -i 100 +``` + +Values below 50 ms are accepted but print a warning to Stderr, because the kernel does not update +the counters that fast and the results will contain zeroes. + +### Output + +This metric provider prints to *Stdout* a continuous stream of data. The format of the data is as follows: + +`TIMESTAMP READING` + +Where: + +- `TIMESTAMP`: Unix timestamp, in microseconds +- `READING`: The CPU utilization across all CPUs, in percent multiplied by 100 + +Any errors are printed to Stderr. + +### How it works + +The provider is a compiled C binary that calls +`host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, ...)` once per interval. This +returns per-CPU tick counters for the `USER`, `SYSTEM`, `NICE` and `IDLE` states. + +For every CPU the binary computes the deltas against the previous sample and derives: + +```C +in_use = d(USER) + d(SYSTEM) + d(NICE) +total = in_use + d(IDLE) +util = in_use / total +``` + +The per-CPU ratios are summed, divided by the number of CPUs, and multiplied by 100 * 100 to give +an integer percentage with two decimals of resolution. + +The previous sample buffer is released with `vm_deallocate()` on every iteration, so the binary +does not leak the Mach-allocated arrays. + +### Caveats + +- The **first** reading has no previous sample to compare against. It therefore uses the absolute + counters, which have been accumulating since boot, and reports the average utilization since + boot rather than the utilization of the interval. Only the second and later readings represent + the configured interval. +- The value is a system-wide average across all CPUs. It includes everything running on the + machine, not just the measured workload. +- `NICE` time is counted as in-use, `IDLE` is counted as idle. +- This provider only works on **macOS**. It relies on the Mach host interface. +- On Apple Silicon the efficiency and performance cores are averaged together without weighting, + so the value does not reflect the asymmetric capacity of the cores. + +### Troubleshooting + +- **`There was an error getting CPU info: `** — the `host_processor_info()` call failed. + The message is the Mach error string. +- **`The call was successful but the data is wrong.`** — the kernel reported zero CPUs. This is + returned by the `-c` check mode when the data cannot be trusted. +- **`A value of is to small. Results will include 0s as the kernel does not update as fast.`** — + the configured `sampling_rate` is below 50 ms. Raise it. diff --git a/content/en/docs/measuring/metric-providers/cpu-utilization-procfs-system.md b/content/en/docs/measuring/metric-providers/cpu-utilization-procfs-system.md index ba15635..54ab4e1 100644 --- a/content/en/docs/measuring/metric-providers/cpu-utilization-procfs-system.md +++ b/content/en/docs/measuring/metric-providers/cpu-utilization-procfs-system.md @@ -24,7 +24,7 @@ This metric provider calculates an estimate of the % total CPU usage based of th - args - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 @@ -45,12 +45,17 @@ Any errors are printed to Stderr. ### How it works -The provider reads all the entries of the first line of the [`/proc/stat` file](https://www.kernel.org/doc/html/latest/filesystems/proc.html) and -uses the argument the same way `htop` does it. This means that CPU Utilization is +The provider reads the aggregate `cpu` line of the [`/proc/stat` file](https://www.kernel.org/doc/html/latest/filesystems/proc.html). CPU Utilization is calcuated as: -`user_time+nice_time+system_time+irq_time+softirq_time+steal_time / wait_time,iowait_time+user_time+nice_time+system_time+irq_time+softirq_time+steal_time` +`user_time+nice_time+system_time / user_time+nice_time+system_time+idle_time+iowait_time+irq_time+softirq_time` -**io_wait** and **wait** are counted both as idle. +Only **user**, **nice** and **system** are counted as compute time. **idle**, **iowait**, **irq** and +**softirq** are all counted as non-compute time. This differs from `htop`, which counts **irq** and +**softirq** as busy. + +**steal** is not read at all. It is zero on non-virtualized systems, and in a virtualized environment +we make the case that this is time spent outside of the system we are looking at, so it is not work +this reporter should capture. Since we want the output as a ratio that can be expressed as an integer, we multiply with 10000. diff --git a/content/en/docs/measuring/metric-providers/disk-io-cgroup-container.md b/content/en/docs/measuring/metric-providers/disk-io-cgroup-container.md index e0a940a..daa5e3a 100644 --- a/content/en/docs/measuring/metric-providers/disk-io-cgroup-container.md +++ b/content/en/docs/measuring/metric-providers/disk-io-cgroup-container.md @@ -60,14 +60,15 @@ The provider: - SCSI CD-ROM (major 11) - ALSA sound devices (major 116) - Xen virtual block devices (major 202) -- only counts whole disk devices (minor number divisible by 16) + - Static Device Mapper devices, e.g. LVM or cryptsetup (majors 251 - 254) +- only counts whole disk devices, skipping partitions - sums up the read and write bytes across all real disk devices #### Device filtering The provider filters out virtual and non-disk devices to focus on actual disk I/O operations that consume energy. It checks the major device numbers against a list of known virtual devices and excludes them from the calculations. -If partition devices are encountered (minor number not divisible by 16), the provider will exit with an error as this should not happen in a properly configured container environment. +A device is detected as a partition by checking whether `/sys/dev/block/:/partition` exists. If a partition is encountered, the provider will exit with an error as this should not happen in a properly configured container environment. #### Attribution of disk I/O diff --git a/content/en/docs/measuring/metric-providers/disk-io-cgroup-system.md b/content/en/docs/measuring/metric-providers/disk-io-cgroup-system.md index 9bfb820..517c2e5 100644 --- a/content/en/docs/measuring/metric-providers/disk-io-cgroup-system.md +++ b/content/en/docs/measuring/metric-providers/disk-io-cgroup-system.md @@ -25,7 +25,7 @@ It can be used for system monitoring and tracking background processes such as t - `-s`: cgroup name strings separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s org.gnome.Shell@wayland.service,session-2.scope diff --git a/content/en/docs/measuring/metric-providers/disk-io-procfs-system.md b/content/en/docs/measuring/metric-providers/disk-io-procfs-system.md index d9a46ba..a2bd7df 100644 --- a/content/en/docs/measuring/metric-providers/disk-io-procfs-system.md +++ b/content/en/docs/measuring/metric-providers/disk-io-procfs-system.md @@ -57,16 +57,17 @@ The provider: - SCSI CD-ROM (major 11) - ALSA sound devices (major 116) - Xen virtual block devices (major 202) -- only counts whole disk devices (minor number divisible by 16), skipping partitions + - Static Device Mapper devices, e.g. LVM or cryptsetup (majors 251 - 254) +- only counts whole disk devices, skipping partitions - outputs statistics for each qualifying disk device #### Device filtering -The provider filters out virtual and non-disk devices to focus on actual physical disk devices that consume energy. Partition devices (minor number not divisible by 16) are also skipped to avoid double-counting, as the whole disk statistics already include all partition activity. +The provider filters out virtual and non-disk devices to focus on actual physical disk devices that consume energy. A device is detected as a partition by checking whether `/sys/dev/block/:/partition` exists. Partitions are skipped to avoid double-counting, as the whole disk statistics already include all partition activity. #### Sectors vs Bytes -The output is in sectors rather than bytes. To convert to bytes, multiply by the sector size (typically 512 bytes for most devices, but can vary). The sector size can be obtained from `/sys/block//queue/logical_block_size`. +The output is in sectors rather than bytes. To convert to bytes, multiply by the sector size (typically 512 bytes for most devices, but can vary). The provider reads the sector size from `/sys/block//queue/hw_sector_size`. #### System-wide monitoring diff --git a/content/en/docs/measuring/metric-providers/disk-used-statvfs-system.md b/content/en/docs/measuring/metric-providers/disk-used-statvfs-system.md index 3f5815a..287eaf9 100644 --- a/content/en/docs/measuring/metric-providers/disk-used-statvfs-system.md +++ b/content/en/docs/measuring/metric-providers/disk-used-statvfs-system.md @@ -58,7 +58,7 @@ This provider uses `statvfs()` which is the POSIX-compliant version of filesyste #### Free space calculation -The provider uses `f_bfree` (free blocks available to superuser) rather than `f_bavail` (free blocks available to non-privileged users) to calculate free space. This means the "used" calculation includes space reserved for the superuser, providing a more accurate representation of actual disk utilization. +The provider uses `f_bfree` (free blocks available to superuser) rather than `f_bavail` (free blocks available to non-privileged users) to calculate free space. Since `f_bfree` counts the superuser-reserved blocks as free, the "used" calculation excludes that reserve and reports only the blocks actually consumed, providing a more accurate representation of actual disk utilization. Using `f_bavail` instead would report the untouched superuser reserve as used. #### Root filesystem monitoring diff --git a/content/en/docs/measuring/metric-providers/docker-stats.md b/content/en/docs/measuring/metric-providers/docker-stats.md index 576f995..0865412 100644 --- a/content/en/docs/measuring/metric-providers/docker-stats.md +++ b/content/en/docs/measuring/metric-providers/docker-stats.md @@ -1,5 +1,15 @@ +--- +title: "Docker Stats" +description: "Reference note on how Docker calculates its own CPU and memory statistics" +date: 2022-06-23T08:49:15+00:00 +draft: false +images: [] +weight: 101 +--- -# Docker Stats +{{< callout context="caution" icon="outline/alert-triangle" >}} +There is no Docker Stats provider in the Green Metrics Tool. This page is only kept as a reference note on how `docker stats` itself calculates its values. +{{< /callout >}} Here the calculation of CPU and memory is shown: diff --git a/content/en/docs/measuring/metric-providers/gpu-energy-nvidia-nvml-component.md b/content/en/docs/measuring/metric-providers/gpu-energy-nvidia-nvml-component.md index 60a186f..1398cbb 100644 --- a/content/en/docs/measuring/metric-providers/gpu-energy-nvidia-nvml-component.md +++ b/content/en/docs/measuring/metric-providers/gpu-energy-nvidia-nvml-component.md @@ -56,7 +56,7 @@ Check in `sudo dmesg` if the kernel module could correctly be lodaded and then v - args - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 @@ -66,13 +66,15 @@ By default the measurement interval is 100 ms. This metric provider prints to Stdout a continuous stream of data. The format of the data is as follows: -`TIMESTAMP READING` +`TIMESTAMP READING CARD-NAME` Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The energy used by the GPU in milliWatts (Ex: 12230 for 12.23 Watts) -- `CARD NAME`: The name of the graphics card as reported by the driver +- `READING`: The current power draw of the GPU in milliWatts (Ex: 12230 for 12.23 Watts) +- `CARD-NAME`: The name of the graphics card as reported by the driver + +The power values are converted to energy in micro Joules when the log file is parsed. Any errors are printed to Stderr. diff --git a/content/en/docs/measuring/metric-providers/lm-sensors.md b/content/en/docs/measuring/metric-providers/lm-sensors.md index 2b08208..f8afe4c 100644 --- a/content/en/docs/measuring/metric-providers/lm-sensors.md +++ b/content/en/docs/measuring/metric-providers/lm-sensors.md @@ -62,7 +62,7 @@ Core 3: +29.0°C (high = +100.0°C, crit = +100.0°C) Your config could be: ```bash -lmsensors.temperature.provider.LmsensorsTempComponentProvider: +lmsensors_temperature_component: sampling_rate: 100 chips: ['coretemp-isa-0000'] features: ['Package id 0', 'Core 0', 'Core 1', 'Core 2', 'Core 3'] @@ -73,7 +73,7 @@ As the matching is open ended you could also only use `'Core'` instead of naming ### Classname - `LmsensorsFanComponentProvider` -- `LmsensorsTempComponentProvider` +- `LmsensorsTemperatureComponentProvider` these both extend the `LmsensorsProvider` which makes it very easy to add new specific providers. We need to separate fan and temperature because they both come in different units. Temp in °C or °F and fan speeds in RPM. @@ -81,7 +81,7 @@ fan and temperature because they both come in different units. Temp in °C or ° ### Metric Name - `lmsensors_fan_component` -- `lmsenors_temp_component` +- `lmsensors_temperature_component` ### Input Parameters @@ -99,7 +99,7 @@ when configuring. The tool also accepts more general parameters: -- `-i`: interval in milliseconds. By default the measurement interval is 100 ms. +- `-i`: interval in milliseconds. By default the measurement interval is 1000 ms. - `-s`: it is possible to pass in a `lm-sensors` config file if you don't want to use the system one. diff --git a/content/en/docs/measuring/metric-providers/memory-energy-RAPL-MSR-component.md b/content/en/docs/measuring/metric-providers/memory-energy-RAPL-MSR-component.md index cdd314e..cad81ba 100644 --- a/content/en/docs/measuring/metric-providers/memory-energy-RAPL-MSR-component.md +++ b/content/en/docs/measuring/metric-providers/memory-energy-RAPL-MSR-component.md @@ -8,9 +8,9 @@ weight: 170 --- ### What it does -This metric provider reads the DRAM energy from the Running Average Power Limit (RAPL) interface via a machine specific registers (MSR) that is present on most modern Intel processers. In depth information about RAPL can be found in the [Intel Software Developer Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +This metric provider reads the DRAM energy from the Running Average Power Limit (RAPL) interface via a machine specific registers (MSR). Unlike the CPU package domain, the DRAM domain is only exposed by a subset of Intel processers. AMD processors do not expose it at all and the provider will refuse to start on them. In depth information about RAPL can be found in the [Intel Software Developer Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). -This MSR keeps a running count of the energy used in a specified domain in microJoules. This metric provider specifically reads from the `energy-pkg` domain, which gives you the energy used by all the domains. +This MSR keeps a running count of the energy used in a specified domain in microJoules. This metric provider specifically reads from the DRAM domain (`MSR_DRAM_ENERGY_STATUS`, `0x619`), which gives you the energy used by the memory controller and the attached DIMMs. ### Setup @@ -64,12 +64,14 @@ Any errors are printed to Stderr. We use a modified version of the open source code found here: ([github](https://github.com/deater/uarch-configure/blob/master/rapl-read/rapl-read.c)) -First we check if the DRAM is compatible by reading the cpu info from `/proc/cpuinfo` and checking against the following list of supported CPUs: +First we detect the CPU by reading the cpu info from `/proc/cpuinfo`. The detected model is then checked against the list of CPUs that expose a DRAM domain: ```txt -CPU_SANDYBRIDGE, CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_BROADWELL_DE, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_SILVERMONT, CPU_ATOM_AIRMONT, CPU_ATOM_MERRIFIELD, CPU_ATOM_MOOREFIELD, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_TIGER_LAKE +CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_ATOM_DENVERTON ``` +Models that the provider knows but that are not in this list — the non-EP *Sandy Bridge* / *Ivy Bridge*, *Broadwell DE*, the *Silvermont*, *Airmont*, *Merrifield* and *Moorefield* Atoms, *Tiger Lake* and AMD family 17h / 19h — have no DRAM domain configured. The provider will exit with *DRAM not available for your processer* on them. + It reads the values from `/dev/cpu/%d/msr` Note that since it reads the energy used by the entire system, any other load that your system has during a program's usage run will also be captured in the energy measurement. diff --git a/content/en/docs/measuring/metric-providers/memory-used-cgroup-container.md b/content/en/docs/measuring/metric-providers/memory-used-cgroup-container.md index eb5f8ea..d958fd2 100644 --- a/content/en/docs/measuring/metric-providers/memory-used-cgroup-container.md +++ b/content/en/docs/measuring/metric-providers/memory-used-cgroup-container.md @@ -25,7 +25,7 @@ It reads the amount of memory, in bytes, used by the cgroup of a container. More - `-s`: container-ids separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s 7f38a4c25fb8f9d5f8651d6ed986b3658dba20d1f5fec98a1f71c141c2b48f4b,c3592e1385d63f9c7810470b12aa00f7d6f7c0e2b9981ac2bdb4371126a0660a diff --git a/content/en/docs/measuring/metric-providers/memory-used-cgroup-system.md b/content/en/docs/measuring/metric-providers/memory-used-cgroup-system.md index 8b11261..2f2e52d 100644 --- a/content/en/docs/measuring/metric-providers/memory-used-cgroup-system.md +++ b/content/en/docs/measuring/metric-providers/memory-used-cgroup-system.md @@ -27,7 +27,7 @@ It can be used for system monitoring and tracking background processes such as t - `-s`: cgroup name strings separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s org.gnome.Shell@wayland.service,session-2.scope diff --git a/content/en/docs/measuring/metric-providers/memory-used-procfs-system.md b/content/en/docs/measuring/metric-providers/memory-used-procfs-system.md new file mode 100644 index 0000000..6fc7a51 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/memory-used-procfs-system.md @@ -0,0 +1,116 @@ +--- +title: "Memory Used - procfs - system" +description: "Documentation of MemoryUsedProcfsSystemProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 182 +--- + +### What it does + +This metric provider measures the memory currently in use on the whole system by reading +`/proc/meminfo`. + +It is the system-wide counterpart to the +[Memory Used cgroup container provider]({{< relref "memory-used-cgroup-container" >}}) and is +deliberately calculated in a way that is comparable to it. + +### Classname + +- `MemoryUsedProcfsSystemProvider` + +### Metric Name + +- `memory_used_procfs_system` + +### Unit + +- `Bytes` + +### Configuration + +The provider lives in the `linux` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + linux: + memory_used_procfs_system: + sampling_rate: 99 +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to the binary as `-i`. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +- args + - `-i` / `--interval`: interval in milliseconds + - `-c` / `--check`: check/test mode — verifies that `/proc/meminfo` can be opened and exits + - `-h` / `--help`: prints usage and exits + +By default the measurement interval is 1000 ms. + +```bash +./metric-provider-binary -i 100 +``` + +### Output + +This metric provider prints to *Stdout* a continuous stream of data. The format of the data is as follows: + +`TIMESTAMP READING` + +Where: + +- `TIMESTAMP`: Unix timestamp, in microseconds +- `READING`: The memory in use in *Bytes* + +Any errors are printed to Stderr. + +### How it works + +The provider is a compiled C binary that parses `/proc/meminfo` on every interval and sums four +fields: + +- `Active` — contains anon and file, equivalent to what the cgroup provider sees +- `SUnreclaim` — slab memory that cannot be reclaimed +- `Percpu` — per-CPU allocator memory +- `Unevictable` — memory that cannot be swapped out + +The values in `/proc/meminfo` are in kiB, so the total is multiplied by 1024 to arrive at Bytes. + +The selection mirrors the cgroup memory provider with one deliberate difference: `shmem` is **not** +subtracted here. On the level of the whole operating system we do want to account for shared +memory, whereas inside a cgroup it would be double-counted. Inactive memory needs no subtraction, +as it is not part of the summed fields to begin with. + +If any of the four fields cannot be found in `/proc/meminfo` the binary aborts with an error rather +than reporting a partial total. An integer overflow while summing also aborts the binary. + +Unlike the MSR-based providers, this binary needs no special privileges — `/proc/meminfo` is +world-readable — and is therefore not installed setuid. + +### Caveats + +- This is a system-wide value. It includes the operating system and every other process on the + machine, not just the measured workload. For attributing memory to your containers use the + [Memory Used cgroup container provider]({{< relref "memory-used-cgroup-container" >}}). +- "Memory used" has no single correct definition on Linux. This provider implements one specific + sum (see above). Do not expect it to match `free`, `htop` or `MemAvailable`, which each make + different choices about caches and reclaimable memory. +- The value is a gauge, not a counter. It is the amount in use at the sampling instant, so + allocations and frees that happen entirely between two samples are invisible. + +### Troubleshooting + +- **`Error - Could not open /proc/meminfo for reading`** — `/proc` is not mounted or is not + accessible. This is also what the `-c` check mode reports as `Couldn't open /proc/meminfo`. +- **`Could not match active`** / **`Could not match slab_unreclaimable`** / **`Could not match percpu`** + / **`Could not match unevictable`** — the expected field was not present in `/proc/meminfo`. This + can happen on kernels that do not export all of these fields. +- **`Integer overflow in adding memory`** — the summed value exceeded the range of the accumulator. diff --git a/content/en/docs/measuring/metric-providers/metric-providers-overview.md b/content/en/docs/measuring/metric-providers/metric-providers-overview.md index 58d5346..cac0416 100644 --- a/content/en/docs/measuring/metric-providers/metric-providers-overview.md +++ b/content/en/docs/measuring/metric-providers/metric-providers-overview.md @@ -28,31 +28,31 @@ ie. `cpu.utilization.cgroup.container` ### Setup and Structure -To use the metrics provider, the C source must be compiled. This can be done easily for all metrics providers by running the `install.sh` script in the project's root directory, or individually by running the `Makefile` in each provider's subdirectory. This will create a binary file in each metric's subdirectory. +To use the metrics provider, the C source must be compiled. This can be done easily for all metrics providers by running the platform install script in the project's root directory (`install_linux.sh`, `install_mac.sh` or `install_windows.ps1`), or individually by running the `Makefile` in each provider's subdirectory. This will create a binary file in each metric's subdirectory. Each metric providers to be attached and used during a run are defined in our `config.yml` file: ```yml measurement: - metric-providers: + metric_providers: linux: - cpu.utilization.cgroup.container.provider.CpuUtilizationCgroupContainerProvider: + cpu_utilization_cgroup_container: sampling_rate: 100 - cpu.energy.RAPL.MSR.system.provider.CpuEnergyRaplMsrSystemProvider: + cpu_energy_rapl_msr_component: sampling_rate: 100 -# psu.energy.ac.xgboost.system.provider.PsuEnergyAcXgboostSystemProvider: -# sampling_rate: 100 +# psu_energy_ac_xgboost_machine: # This is a default configuration. Please change this to your system! # CPUChips: 1 # HW_CPUFreq: 3100 # CPUCores: 28 +# CPUThreads: 56 # TDP: 150 # HW_MemAmountGB: 16 ``` The dimension of the sampling_rate is milliseconds. Change this number to have a smaller or larger time window between measurements for that specific provider. -The metric providers are written as C programs with a Python wrapper, and live under `metric_providers/` in the subdirectory that matches the `config.yml`. The directory contains the following files: +Most metric providers are written as C programs with a Python wrapper, and live under `metric_providers/` in the subdirectory that matches the `config.yml`. The directory contains the following files: ```txt - : @@ -63,6 +63,8 @@ The metric providers are written as C programs with a Python wrapper, and live u The `source.c` is the main sourcecode for the metric provider, the `Makefile` can be used to generate the needed binary, and the `provider.py` is the python wrapper. +Not every provider has a `source.c` though. Providers that read from an API (`carbon_intensity_*_machine`), that wrap an external command (`lmsensors_*_component`, `psu_energy_ac_ipmi_machine`) or that derive their values from another provider's data (`psu_energy_ac_xgboost_machine`) only ship a `provider.py`. + ### How to Use The `runner.py` will instrument all the metric providers automatically for you. It will save all the measured data into the postgres database. @@ -73,7 +75,7 @@ To activate a metric provider simply uncomment the line where it's name appears. #### C -After building the metric provider binary via the `Makefile` or `install.sh` script, simply run it. +After building the metric provider binary via the `Makefile` or the platform install script, simply run it. It will begin reading the metrics and printing them to Stdout. @@ -93,13 +95,13 @@ Some special providers may register additional output fields, that are considere ``` -The timestamp will always be a UNIX timestamp, down to the microsecond. The metric_reading output and units are specific to each metric, and the container-id will also only be shown if the metric reads on a container level (otherwise it should say SYSTEM). +The timestamp will always be a UNIX timestamp, down to the microsecond. The metric_reading output and units are specific to each metric, and the container-id will only be shown if the metric reads on a container level. Providers that read system-wide simply omit the third column. #### Python To use the Python wrapper, call the `start_profiling` method when you wish to begin the profiling, and then `stop_profiling` when you wish to stop. -You may pass in a container-id into `start_profiling` if needed. It writes the output of the metrics to `/tmp/green-metrics-tool/{self._metric_name}.log"`, which can be read programmatically with the `read_metrics function`. +`start_profiling` takes no arguments. The containers to be profiled are passed into the provider's constructor instead. It writes the output of the metrics to `/tmp/green-metrics-tool/metrics/{self._metric_name}.log"`, which can be read programmatically with the `read_metrics function`. ### Writing your own metric provider diff --git a/content/en/docs/measuring/metric-providers/network-connections-proxy-container.md b/content/en/docs/measuring/metric-providers/network-connections-proxy-container.md index 9dfc9af..9d515c1 100644 --- a/content/en/docs/measuring/metric-providers/network-connections-proxy-container.md +++ b/content/en/docs/measuring/metric-providers/network-connections-proxy-container.md @@ -27,7 +27,9 @@ proxy program and then adds the corresponding values to the `network_intercepts` ### Metric Name -- `network_connections_proxy_container` +- `network_connections_proxy_container_dockerproxy` + +The key to enable the provider in the `config.yml` is `network_connections_proxy_container`. ### How it works @@ -51,7 +53,7 @@ if our logic does not resolve a correct ip on Linux. ```yml common: - network.proxy.proxy_provider.ProxyMetricsProvider: + network_connections_proxy_container: host_ip: 192.168.1.2 ``` diff --git a/content/en/docs/measuring/metric-providers/network-connections-tcpdump-system.md b/content/en/docs/measuring/metric-providers/network-connections-tcpdump-system.md new file mode 100644 index 0000000..c699428 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/network-connections-tcpdump-system.md @@ -0,0 +1,143 @@ +--- +title: "Network Connections - tcpdump - system" +description: "Documentation of NetworkConnectionsTcpdumpSystemProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 191 +--- + +### What it does + +This metric provider captures all network traffic on the machine with `tcpdump` and aggregates it +per IP address and port. It answers the question "which hosts did this run talk to, and how much +data was exchanged". + +Unlike the [Network Connections Proxy Container provider]({{< relref "network-connections-proxy-container" >}}), +which only sees external **http** and **https** connections routed through a proxy, this provider +sees every packet on the wire, including inter-container traffic and non-HTTP protocols. It does +not resolve hostnames. + +This is a **debugging** provider. It is listed under the `DEBUG` section of the `config.yml` and is +disabled by default. + +### Classname + +- `NetworkConnectionsTcpdumpSystemProvider` + +### Metric Name + +- `network_connections_tcpdump_system` + +### Unit + +The provider has **no unit** and produces no numeric time series. See [Output](#output). + +### Configuration + +The provider lives in the `common` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + common: + network_connections_tcpdump_system: + split_ports: True +``` + +Config keys: + +- `split_ports` — defaults to `True`. When `True`, traffic is bucketed per `/` + (e.g. `443/TCP`). When `False`, ports are ignored and traffic is bucketed per protocol only + (e.g. `TCP`). Turn this off when you care about the volume per host rather than per service, or + when a workload uses many ephemeral ports and the per-port breakdown becomes unreadable. + +Note that this provider takes **no `sampling_rate`**. It captures every packet rather than sampling +at an interval, so no `-i` argument is passed to it. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +The provider executes the shell script `tcpdump.sh`, which takes: + +- args + - `-c`: check/test mode — tries to capture a single packet with a 3 second timeout and exits + +In measurement mode the script runs: + +```bash +tcpdump -tt --micro -n -v +``` + +Where `-tt` prints an unformatted Unix timestamp, `--micro` gives microsecond resolution, `-n` +disables name resolution and `-v` produces the verbose output the parser expects. + +### Output + +This provider does **not** write to the `measurement_values` table like the other providers. The +raw `tcpdump` output is parsed at the end of the run and the aggregated result is stored as a +`NETWORK_STATS` log entry on the run itself, where it can be inspected in the run details in the +frontend. + +The stored text is formatted per IP address: + +```text +IP: 93.184.216.34 (as sender or receiver. aggregated) + Total transmitted data: 15320 bytes + Ports: + 443/TCP: 24 packets, 15320 bytes +``` + +Every packet is counted for **both** its source and its destination IP, which is why the report +says *as sender or receiver. aggregated*. + +Empty output is explicitly allowed for this provider — a run with no captured traffic is not an +error. + +### How it works + +On start, `tcpdump.sh` is launched and its output is written to the provider's log file. When the +run is over, the log is parsed line by line in Python. + +The parser recognises several `tcpdump` line shapes, including IPv4 and IPv6 addresses with and +without ports, payload-length lines, `ethertype Unknown` frames and LLDP frames. Addresses are +validated with Python's `ipaddress` module. The following are deliberately ignored: + +- ARP traffic +- Layer-2 control frames (STP, CDP) +- MAC-address-only frames +- Indented detail lines belonging to the preceding packet +- `tcpdump`'s own startup banners on Stdout and Stderr + +A line that matches none of the known shapes is **logged as an error and skipped** rather than +aborting the run. This was a deliberate change: `tcpdump` occasionally emits shapes that have not +been seen before, and losing the whole run over one unparsed line is worse than losing one packet. + +Because this provider watches the containers rather than the machine's energy behaviour, the +scenario runner starts it together with the container providers, not with the system providers. + +### Caveats + +- `tcpdump` requires elevated privileges to put the interface into capture mode. If it cannot be + started, the system check fails with a hint about missing sudo permissions. +- The provider captures **all** traffic on the machine, not just the traffic of your containers. + Anything else running on the measurement host appears in the report. +- Host filtering is **not implemented**. `generate_stats_string()` raises `NotImplementedError` if + `filter_host` is requested, because the `netifaces` library it relied on has been abandoned and + no replacement is in place yet. There is therefore no way to exclude the measurement machine's + own addresses from the report. +- Packet capture adds overhead and writes a large log file on a busy network. This is why the + provider is filed under debugging and is off by default. +- Since every packet is counted for both endpoints, summing "Total transmitted data" across all + IPs counts each byte twice. + +### Troubleshooting + +- **`tcpdump could not be started. Missing sudo permissions?`** — the check mode could not capture + a packet. Verify that `tcpdump` is installed and that it may run without a password prompt. +- **Empty report** — no traffic was captured during the run. On a quiet interface this is normal + and is not treated as an error. +- **`Unmatched tcpdump line` entries in the system logs** — the parser encountered a line shape it + does not know. The packet is skipped; the rest of the report is still valid. Please report the + line so the parser can be extended. diff --git a/content/en/docs/measuring/metric-providers/network-io-cgroup-container.md b/content/en/docs/measuring/metric-providers/network-io-cgroup-container.md index 8b9f12a..0ab6ac7 100644 --- a/content/en/docs/measuring/metric-providers/network-io-cgroup-container.md +++ b/content/en/docs/measuring/metric-providers/network-io-cgroup-container.md @@ -23,7 +23,7 @@ It reads the total amount of sent and received bytes from the network interface - `-s`: container-ids separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s 7f38a4c25fb8f9d5f8651d6ed986b3658dba20d1f5fec98a1f71c141c2b48f4b,c3592e1385d63f9c7810470b12aa00f7d6f7c0e2b9981ac2bdb4371126a0660a @@ -33,14 +33,18 @@ By default the measurement interval is 100 ms. This metric provider prints to Stdout a continuous stream of data. The format of the data is as follows: -`TIMESTAMP READING CONTAINER-ID` +`TIMESTAMP RECEIVED TRANSMITTED CONTAINER-ID` Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The amount of memory, in bytes, used during the time interval +- `RECEIVED`: The cumulative amount of bytes received, as reported by the interface counters +- `TRANSMITTED`: The cumulative amount of bytes transmitted, as reported by the interface counters - `CONTAINER-ID`: The container ID that this reading is for +The values are the raw counters. The amount of traffic during an interval is calculated as the +difference between two consecutive readings when the log file is parsed. + Any errors are printed to Stderr. ### How it works diff --git a/content/en/docs/measuring/metric-providers/network-io-cgroup-system.md b/content/en/docs/measuring/metric-providers/network-io-cgroup-system.md index 365dfd8..7d7fbff 100644 --- a/content/en/docs/measuring/metric-providers/network-io-cgroup-system.md +++ b/content/en/docs/measuring/metric-providers/network-io-cgroup-system.md @@ -25,7 +25,7 @@ It can be used for system monitoring and tracking background processes such as t - `-s`: cgroup name strings separated by commas - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 -s org.gnome.Shell@wayland.service,session-2.scope @@ -35,14 +35,18 @@ By default the measurement interval is 100 ms. This metric provider prints to Stdout a continuous stream of data. The format of the data is as follows: -`TIMESTAMP READING CGROUP-NAME` +`TIMESTAMP RECEIVED TRANSMITTED CGROUP-NAME` Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The amount of network bytes (sent and received), in bytes, during the time interval +- `RECEIVED`: The cumulative amount of bytes received, as reported by the interface counters +- `TRANSMITTED`: The cumulative amount of bytes transmitted, as reported by the interface counters - `CGROUP-NAME`: The cgroup name that this reading is for +The values are the raw counters. The amount of traffic during an interval is calculated as the +difference between two consecutive readings when the log file is parsed. + Any errors are printed to Stderr. ### How it works diff --git a/content/en/docs/measuring/metric-providers/network-io-procfs-system.md b/content/en/docs/measuring/metric-providers/network-io-procfs-system.md index adac032..d76451e 100644 --- a/content/en/docs/measuring/metric-providers/network-io-procfs-system.md +++ b/content/en/docs/measuring/metric-providers/network-io-procfs-system.md @@ -24,7 +24,7 @@ monitoring system-wide network usage independent of containers. - args - `-i`: interval in milliseconds -By default the measurement interval is 100 ms. +By default the measurement interval is 1000 ms. ```bash ./metric-provider-binary -i 100 diff --git a/content/en/docs/measuring/metric-providers/overhead-of-measurement-providers.md b/content/en/docs/measuring/metric-providers/overhead-of-measurement-providers.md index 5ff43bb..732e16c 100644 --- a/content/en/docs/measuring/metric-providers/overhead-of-measurement-providers.md +++ b/content/en/docs/measuring/metric-providers/overhead-of-measurement-providers.md @@ -35,12 +35,12 @@ The script produces a lot of output, but what you want to look out for is: Configured reporters -- PsuEnergyAcMCPMachineProvider: 99 ms sampling_rate +- PsuEnergyAcMcpMachineProvider: 99 ms sampling_rate - NetworkIoCgroupContainerProvider: 99 ms sampling_rate - CpuEnergyRaplMsrComponentProvider: 99 ms sampling_rate - MemoryEnergyRaplMsrComponentProvider: 99 ms sampling_rate - CpuUtilizationProcfsSystemProvider: 99 ms sampling_rate -- MemoryTotalCgroupContainerProvider: 99 ms sampling_rate +- MemoryUsedCgroupContainerProvider: 99 ms sampling_rate - CpuUtilizationCgroupContainerProvider: 99 ms sampling_rate - LmsensorsTemperatureComponentProvider: 99 ms sampling_rate @@ -95,7 +95,7 @@ Configured reporters - CpuEnergyRaplMsrComponentProvider: 99 ms sampling_rate - MemoryEnergyRaplMsrComponentProvider: 99 ms sampling_rate - CpuUtilizationProcfsSystemProvider: 99 ms sampling_rate -- MemoryTotalCgroupContainerProvider: 99 ms sampling_rate +- MemoryUsedCgroupContainerProvider: 99 ms sampling_rate - CpuUtilizationCgroupContainerProvider: 99 ms sampling_rate - LmsensorsTemperatureComponentProvider: 99 ms sampling_rate @@ -132,7 +132,7 @@ Configured reporters ### Summary: -- Used reporter for CPU energy was [MCP]({{< relref "/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component" >}}) +- Used reporter for CPU energy was [RAPL]({{< relref "/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component" >}}) - Effective CPU energy overhead in a loaded system is **0.65 %** - Idle CPU energy overhead in an idle system is **126 %** - As stated before, use this value only for debugging in low power systems @@ -142,12 +142,12 @@ Configured reporters Configured reporters -- PsuEnergyAcMCPMachineProvider: 99 ms sampling_rate +- PsuEnergyAcMcpMachineProvider: 99 ms sampling_rate - NetworkIoCgroupContainerProvider: 99 ms sampling_rate - CpuEnergyRaplMsrComponentProvider: 99 ms sampling_rate - MemoryEnergyRaplMsrComponentProvider: 99 ms sampling_rate - CpuUtilizationProcfsSystemProvider: 99 ms sampling_rate -- MemoryTotalCgroupContainerProvider: 99 ms sampling_rate +- MemoryUsedCgroupContainerProvider: 99 ms sampling_rate - CpuUtilizationCgroupContainerProvider: 99 ms sampling_rate - LmsensorsTemperatureComponentProvider: 99 ms sampling_rate @@ -198,7 +198,7 @@ Configured reporters - CpuEnergyRaplMsrComponentProvider: 99 ms sampling_rate - MemoryEnergyRaplMsrComponentProvider: 99 ms sampling_rate - CpuUtilizationProcfsSystemProvider: 99 ms sampling_rate -- MemoryTotalCgroupContainerProvider: 99 ms sampling_rate +- MemoryUsedCgroupContainerProvider: 99 ms sampling_rate - CpuUtilizationCgroupContainerProvider: 99 ms sampling_rate - LmsensorsTemperatureComponentProvider: 99 ms sampling_rate @@ -235,7 +235,7 @@ Configured reporters ### Summary: -- Used reporter for CPU energy was [MCP]({{< relref "/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component" >}}) +- Used reporter for CPU energy was [RAPL]({{< relref "/docs/measuring/metric-providers/cpu-energy-RAPL-MSR-component" >}}) - The effective CPU energy overhead in a loaded system is **0.9 %** - The idle CPU energy overhead in an idle system is **153 %** - As stated before, use this value only for debugging in low power systems diff --git a/content/en/docs/measuring/metric-providers/powermetrics.md b/content/en/docs/measuring/metric-providers/powermetrics.md new file mode 100644 index 0000000..87c0128 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/powermetrics.md @@ -0,0 +1,171 @@ +--- +title: "Powermetrics" +description: "Documentation of PowermetricsProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 230 +--- + +### What it does + +This metric provider wraps Apple's `/usr/bin/powermetrics` tool on **macOS** and extracts energy, +CPU time and disk I/O data from it. + +On macOS this is the primary provider. Because `powermetrics` reports the energy of the CPU, GPU +and Neural Engine as well as the resource usage of the Docker VM, a single provider covers what +takes several providers on Linux. The `config.yml.example` accordingly notes: *On Mac you only need +this provider. Please remove all others!* + +### Classname + +- `PowermetricsProvider` + +### Metric Name + +- `powermetrics` + +This is the name the provider registers under, but it is **not** what appears in the database. The +provider inlines several metrics and sets their names individually while parsing. See +[Output](#output) for the actual metric names. + +### Unit + +- `uJ` + +This is the provider's default unit. The inlined metrics each carry their own unit — see +[Output](#output). + +### Configuration + +The provider lives in the `macos` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + macos: + powermetrics: + sampling_rate: 499 # If you set this value too low powermetrics will not be able to accommodate the timing. We recommend no lower than 199 ms +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to `powermetrics` as `-i`. The recommended + value is `499`, and we recommend **no lower than 199 ms**: below that `powermetrics` cannot keep + up with the requested timing. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +The provider calls the system binary `/usr/bin/powermetrics` with `sudo` and appends a fixed set of +switches: + +```bash +sudo /usr/bin/powermetrics -i 499 --show-process-io --show-process-gpu --show-process-netstats --show-process-energy --show-process-coalition -f plist -b 0 +``` + +Where: + +- `-i`: interval in milliseconds, taken from `sampling_rate` +- `--show-process-*`: enable the individual sample groups the parser needs +- `-f plist`: emit plist rather than human-readable text +- `-b 0`: no buffering + +The individual `--show-process-*` switches are used instead of `--show-all`, because `--show-all` +sometimes triggers output on Stderr, which the tool treats as a provider failure. + +### Output + +`powermetrics` writes a stream of binary plist documents, separated by null bytes (`\x00`), which +the provider parses at the end of the run. Rather than one time series, it produces several metrics +at once: + +| Metric | detail_name | Unit | Source | +|---|---|---|---| +| `cpu_energy_powermetrics_component` | `[COMPONENT]` | `uJ` | `processor.package_joules` | +| `cores_energy_powermetrics_component` | `[COMPONENT]` | `uJ` | `processor.cpu_power` | +| `gpu_energy_powermetrics_component` | `[COMPONENT]` | `uJ` | `processor.gpu_power` | +| `ane_energy_powermetrics_component` | `[COMPONENT]` | `uJ` | `processor.ane_power` (Apple Neural Engine) | +| `cpu_time_powermetrics_vm` | `docker_vm` | `ns` | Docker coalition `cputime_ns` | +| `disk_io_bytesread_powermetrics_vm` | `docker_vm` | `Bytes` | Docker coalition `diskio_bytesread` | +| `disk_io_byteswritten_powermetrics_vm` | `docker_vm` | `Bytes` | Docker coalition `diskio_byteswritten` | +| `energy_impact_powermetrics_vm` | `docker_vm` | `*` | Docker coalition `energy_impact` | + +Each field is only emitted if it is present in the sample, so which metrics you get depends on the +hardware and on whether Docker was running. + +The `energy_impact` metric uses the unit `*`. This is deliberate: energy impact is an +Apple-internal scoring value whose definition is +[not publicly documented](https://tinyurl.com/2p9c56pz), so we cannot map it to a physical unit. + +### How it works + +Timestamps are reconstructed rather than read per sample. The provider takes the `timestamp` of the +first document as the anchor and then accumulates each document's `elapsed_ns`, so the time series +follows the intervals `powermetrics` actually achieved rather than the ones that were requested. + +The energy conversion exploits the units `powermetrics` already uses. `cpu_power`, `gpu_power` and +`ane_power` are reported in mW, so multiplying by the elapsed time in milliseconds +(`elapsed_ns / 1_000_000`) yields microjoules directly. `package_joules` is already an energy value +and is simply multiplied by 1,000,000. + +The Docker VM data comes from the `coalitions` list, where the provider looks for the entry named +`com.docker.docker`. If Docker is not running the VM metrics are simply absent. + +### Health check + +Before the run the provider counts running `powermetrics` processes with `pgrep -ix powermetrics`. +If any instance is already running it refuses to start, because a second instance would interfere +with the measurement. You can override this with `--dev-no-system-checks`. + +The count taken at startup is remembered and used again on shutdown to detect whether *our* +instance has actually terminated. + +### Shutdown + +Stopping `powermetrics` is more involved than for other providers. Because it runs under `sudo`, +the tool cannot signal it directly. The provider therefore: + +1. Sends `SIGIO` to ask the process to flush. This is common practice; the process does not appear + to react to it, but it is kept as it does no harm. +2. Tries the normal termination path, which fails with a `PermissionError` due to the missing root + permissions. +3. Falls back to `sudo /usr/bin/killall powermetrics`. +4. Waits (up to 60 seconds) until the process is really gone, so that it has time to flush its + output to disk. + +If the process is still alive after 60 seconds it is killed with `kill -9` and a `RuntimeError` is +raised, because a `powermetrics` that did not flush cleanly may have produced truncated data: +*"Values can not be trusted!"* + +### Caveats + +- **`killall` kills every `powermetrics` process on the system**, not just ours. If you had other + instances running — for example the [hog](https://github.com/green-coding-solutions/hog) — they + will be terminated too. The hog restarts itself, but manually started instances will not; the + provider prints a notice when this happens. Keeping only our PID and killing that is not possible + without root, and a `sudoers` entry with a PID wildcard would open a security hole. +- A `sampling_rate` below 199 ms is not honoured reliably: `powermetrics` cannot accommodate the + timing and the effective intervals will drift away from what you configured. +- The resolution underflow check is disabled for this provider, because `powermetrics` data is + frequently sparse and legitimately reports 0 for idle components. +- Some Stderr output from `powermetrics` is filtered out and ignored, specifically lines containing + `proc_pid` and `Second underflow occured`. These appear sporadically, are not correlated with the + interval, and are not documented by Apple; since the tool aborts a run on unexpected Stderr, they + are suppressed rather than treated as failures. +- If a container stops very quickly the log file can be empty, because `powermetrics` takes some + time to start up. In that case no data is recorded for the run. +- The energy values are component-level values for the whole machine. They are not attributed to + individual containers. + +### Troubleshooting + +- **`Another instance of powermetrics is already running on the system!`** — close it before + running the Green Metrics Tool, or override with `--dev-no-system-checks`. +- **`powermetrics had to be killed with kill -9. Values can not be trusted!`** — the process did not + terminate within 60 seconds. The run's data should be discarded. +- **`There was an error parsing the powermetrics data!`** — a plist chunk could not be decoded. The + iteration count and the offending chunk are printed to help locate the problem. +- Empty measurements — check that the run was long enough for `powermetrics` to produce at least + one sample. diff --git a/content/en/docs/measuring/metric-providers/psu-energy-ac-gude-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-ac-gude-machine.md new file mode 100644 index 0000000..f3b5392 --- /dev/null +++ b/content/en/docs/measuring/metric-providers/psu-energy-ac-gude-machine.md @@ -0,0 +1,120 @@ +--- +title: "PSU Energy AC - Gude - machine" +description: "Documentation of PsuEnergyAcGudeMachineProvider for the Green Metrics Tool" +date: 2026-07-16T08:49:15+00:00 +draft: false +images: [] +weight: 209 +--- + +### What it does + +This metric provider reads the AC power draw of the whole machine from a +[Gude](https://gude-systems.com/) networked power meter over HTTP and converts it to energy. + +The provider was originally built for the +[Gude Expert Power Control 1202](https://gude-systems.com/en/products/expert-power-control-1202/), +the same power meter used by the [Blauer Engel](https://eco.kde.org/blog/2022-05-30-sprint-lab-setup/) +team for their measurements. It is a slimmed-down version of the vendor's +[check_gude.py](https://github.com/gudesystems/check_gude.py). + +Please note: This metric provider is **no longer officially maintained** by us. It remains in the +code base for backwards compatibility. + +### Classname + +- `PsuEnergyAcGudeMachineProvider` + +### Metric Name + +- `psu_energy_ac_gude_machine` + +### Unit + +- `uJ` + +### Configuration + +The provider lives in the `linux` architecture section of the `config.yml`: + +```yaml +measurement: + metric_providers: + linux: + psu_energy_ac_gude_machine: + sampling_rate: 99 +``` + +Config keys: + +- `sampling_rate` — the interval in milliseconds. Passed to the script as `-i`. + +Please see [Configuration →]({{< relref "/docs/measuring/configuration" >}}) for further info. + +### Input Parameters + +Rather than a compiled binary this provider runs the Python script `check_gude_modified.py`: + +- args + - `-i`: interval in milliseconds. The script exits with the usage text if it is not supplied. + +```bash +./check_gude_modified.py -i 100 +``` + +### Output + +This metric provider prints to *Stdout* a continuous stream of data. The format of the data is as follows: + +`TIMESTAMP READING` + +Where: + +- `TIMESTAMP`: Unix timestamp, in microseconds, taken *after* the HTTP request completed +- `READING`: The energy consumed over the elapsed interval in *uJ* + +Any errors are printed to Stderr. + +### How it works + +The script loops for the lifetime of the run. On each iteration it: + +1. Records a timestamp, sleeps for `sampling_rate` milliseconds. +2. Issues an HTTP GET to the power meter's `status.json` endpoint with the `components=0x4000` + parameter, which asks the device for simple sensor values only. +3. Records a second timestamp and derives the effective elapsed time. +4. Reads the power value out of the JSON response and multiplies it by the elapsed time in + microseconds, yielding microjoules. + +Because the energy is derived from the *effective* elapsed time rather than the requested sleep +time, network latency to the power meter does not silently inflate or deflate the energy total. + +The power value is taken from a fixed position in the response document: +`sensor_values[0].values[0][4].v`. + +### Caveats + +- **The address of the power meter is hardcoded** in `check_gude_modified.py` as + `http://192.168.178.32/status.json`. There is no config option for it. You have to edit the + script to point it at your device. +- TLS verification is disabled and no authentication is sent with the request. The provider expects + the power meter to be reachable unauthenticated on a trusted local network. +- The provider does not ship a `metric-provider-binary`, but it also does not override the default + system check, which expects one. Enabling this provider on a system where the check runs will + therefore fail to find a binary to check. You can bypass the checks with `--dev-no-system-checks`. +- The position of the power value in the JSON is fixed. A device with a different sensor layout, or + a firmware that reorders the document, will yield wrong values rather than an error. +- The reading measures the **whole machine** at the wall socket. It includes every other component + and any other workload on the machine, not just the measured containers. +- The HTTP request has a 15 second timeout. At small sampling rates a slow device will therefore + stall the loop rather than skip a sample. + +### Troubleshooting + +- **`Please supply -i to set sampling_rate in milliseconds`** — the script was called without `-i`. +- **Connection errors / timeouts** — the power meter is not reachable at the hardcoded IP. Verify + that the device answers at `http://192.168.178.32/status.json` from the measurement machine, or + edit the URL in `check_gude_modified.py`. +- **`IndexError` / `KeyError` on `sensor_values`** — the device returned a document that does not + have the expected sensor layout. +- The script needs the `requests` package to be importable in the environment the tool runs in. diff --git a/content/en/docs/measuring/metric-providers/psu-energy-ac-ipmi-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-ac-ipmi-machine.md index 309bd75..4ee8190 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-ac-ipmi-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-ac-ipmi-machine.md @@ -56,6 +56,6 @@ This metric provider prints to stdout a continuous stream of data every `interva Where: - `TIMESTAMP`: Unix timestamp, in microseconds -- `READING`: The value taken from sensors in milliWatts with two significant digits (Ex. 14000 for 14 Watts) +- `READING`: The value taken from sensors in Watts (Ex. 14 for 14 Watts) Any errors are printed to stderr. diff --git a/content/en/docs/measuring/metric-providers/psu-energy-ac-mcp-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-ac-mcp-machine.md index 3653def..bb890e9 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-ac-mcp-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-ac-mcp-machine.md @@ -42,7 +42,7 @@ After that just plug it into your USB and please use Channel 1. ### Input Parameters -- `-i`: interval in milliseconds. By default the measurement interval is 100 ms. +- `-i`: interval in milliseconds. By default the measurement interval is 1000 ms. - `-e`: Output energy instead of power - `-o`: One-Shot mode. Ouput only one reading (In case `-e` is also supplied the first value is non-sensical and will be 0. Only subsequent calls are useful) - `-x`: Dump Range1 (0x00AE) and Range2 (0x00BE) register contents and diff --git a/content/en/docs/measuring/metric-providers/psu-energy-ac-powerspy2-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-ac-powerspy2-machine.md index b484f22..44e9036 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-ac-powerspy2-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-ac-powerspy2-machine.md @@ -61,10 +61,12 @@ To make the tool as useful as possible it takes multiple filter parameters: - `--device`: The filesystem endpoint that should be used for communication. Please make sure it is readable and writeable by the calling process. - `--interval`: Measurement interval in number of ms. Defaults to 1 second. -- `--unit`: Specify the unit, which should be one of: mW, W, mJ, J. Defaults to mW +- `--unit`: Specify the unit, which should be one of: mW, W, mJ, uJ, J. Defaults to mW. The names are + case-sensitive, so `mj` will raise an error. The Green Metrics Tool always calls the provider with + `uJ`. ```bash -> python3 metric-provider.py --unit mj --interval 250 +> python3 metric-provider.py --unit uJ --interval 250 ``` ### Output diff --git a/content/en/docs/measuring/metric-providers/psu-energy-dc-picolog-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-dc-picolog-machine.md index cb4b65c..d2c31f4 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-dc-picolog-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-dc-picolog-machine.md @@ -6,7 +6,7 @@ weight: 213 --- {{< callout context="caution" icon="outline/alert-triangle" >}} -This is a legacy provider and is not maintained anymore. It is only used in an old version of the Green Metrics Tool! +This provider does not ship with the Green Metrics Tool anymore. The code has been removed and this page is only kept as a reference for old versions. Nothing described below can be configured or run on a current installation. {{< /callout >}} ## What it does diff --git a/content/en/docs/measuring/metric-providers/psu-energy-dc-rapl-msr-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-dc-rapl-msr-machine.md index 580172c..80d8b24 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-dc-rapl-msr-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-dc-rapl-msr-machine.md @@ -38,16 +38,20 @@ Please look at [RAPL installation]({{< relref "/docs/installation/installation-l - Args: - i: specifies interval in milliseconds between measurements + - p: measure the *PSYS* domain instead of the CPU package + +Without `-p` the binary measures the CPU package. The Green Metrics Tool always adds this switch, so +when calling the binary directly you have to supply it yourself: ```bash -./metric-provider-binary -i 100 +./metric-provider-binary -i 100 -p ``` ### Output This metric provider prints to Stdout a continuous stream of data. The format of the data is as follows: -`TIMESTAMP ENERGY_OUTPUT` +`TIMESTAMP ENERGY_OUTPUT PSYS_ID` Where: @@ -70,12 +74,16 @@ Any errors are printed to Stderr. We use a modified version of the open source code found here: ([github](https://github.com/deater/uarch-configure/blob/master/rapl-read/rapl-read.c)) -First we check if the CPU is compatible by reading the cpu info from `/proc/cpuinfo` and checking against the following list of supported CPUs: +First we check if the CPU is compatible by reading the cpu info from `/proc/cpuinfo`. The check accepts *Intel* CPUs of family 6 as well as *AMD* CPUs of family 17h / 19h. Any other vendor or family aborts the provider. + +The source knows the following CPU models, which are used to determine which RAPL domains a chip exposes: ```txt -CPU_SANDYBRIDGE, CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_BROADWELL_DE, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_SILVERMONT, CPU_ATOM_AIRMONT, CPU_ATOM_MERRIFIELD, CPU_ATOM_MOOREFIELD, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_TIGER_LAKE +CPU_SANDYBRIDGE, CPU_SANDYBRIDGE_EP, CPU_IVYBRIDGE, CPU_IVYBRIDGE_EP, CPU_HASWELL, CPU_HASWELL_ULT, CPU_HASWELL_GT3E, CPU_HASWELL_EP, CPU_BROADWELL, CPU_BROADWELL_GT3E, CPU_BROADWELL_EP, CPU_BROADWELL_DE, CPU_SKYLAKE, CPU_SKYLAKE_HS, CPU_SKYLAKE_X, CPU_KNIGHTS_LANDING, CPU_KNIGHTS_MILL, CPU_KABYLAKE_MOBILE, CPU_KABYLAKE, CPU_ATOM_SILVERMONT, CPU_ATOM_AIRMONT, CPU_ATOM_MERRIFIELD, CPU_ATOM_MOOREFIELD, CPU_ATOM_GOLDMONT, CPU_ATOM_GEMINI_LAKE, CPU_ATOM_DENVERTON, CPU_TIGER_LAKE, CPU_AMD_FAM17H ``` +Passing the CPU check does not guarantee that the *PSYS* domain is actually present, as it is read from the Intel `MSR_PLATFORM_ENERGY_STATUS` register. The provider therefore verifies on startup that the register returns a plausible value and aborts if it does not. + It reads the values from `/dev/cpu/%d/msr` Note that since it reads the energy used by the entire system, any other load that your system has during a program's usage run will also be captured in the energy measurement. diff --git a/content/en/docs/measuring/metric-providers/psu-energy-sdia-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-sdia-machine.md index d0f312a..5028fc9 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-sdia-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-sdia-machine.md @@ -40,7 +40,7 @@ In the `config.yml` file also the *CpuUtilizationProcfsSystemProvider* must be a The provider cannot be run directly, it only works in conjunction with a run of the Green Metrics Tool. -The provider reads the `/tmp/green-metrics-tool/cpu_utilization_procfs_system.log` file +The provider reads the `/tmp/green-metrics-tool/metrics/cpu_utilization_procfs_system.log` file from the *CpuUtilizationProcfsSystemProvider* in order to keep overhead low and not to double query the utilization from the system. @@ -48,7 +48,7 @@ not to double query the utilization from the system. Since this provider should not be run directly there it has no direct output. -The resulting data however is the wattage for the whole machine (AC Power) in Watts. +The resulting data however is the energy of the whole machine (AC Power) in micro Joules. This value has the same granularity as the one configured in the `config.yml` for the *CpuUtilizationProcfsSystemProvider* diff --git a/content/en/docs/measuring/metric-providers/psu-energy-xgboost-machine.md b/content/en/docs/measuring/metric-providers/psu-energy-xgboost-machine.md index 673d917..d35a4b7 100644 --- a/content/en/docs/measuring/metric-providers/psu-energy-xgboost-machine.md +++ b/content/en/docs/measuring/metric-providers/psu-energy-xgboost-machine.md @@ -38,10 +38,16 @@ The provider must be configured in the `config.yml`. It must be supplied with th - CPUChips - HW_CPUFreq -- CPUCores +- CPUThreads - TDP - HW_MemAmountGB +The following parameters are optional: + +- CPUCores +- Hardware_Availability_Year +- VHost_Ratio + You can find these parameters in your data sheet of the used machine. In case you are using a VM please check [this repository](https://github.com/green-coding-solutions/carbondb-agent) for an example how to derive the values. @@ -57,7 +63,7 @@ In the `config.yml` file the *CpuUtilizationProcfsSystemProvider* must also be a If you want to run the provider directly we advise that you rather check out it's main repository: [XGBoost SPECPower Model documentation](https://github.com/green-coding-solutions/spec-power-model) -The provider reads the `/tmp/green-metrics-tool/cpu_utilization_procfs_system.log` file +The provider reads the `/tmp/green-metrics-tool/metrics/cpu_utilization_procfs_system.log` file from the *CpuUtilizationProcfsSystemProvider* in order to keep overhead low and not to double query the utilization from the system. @@ -65,7 +71,7 @@ not to double query the utilization from the system. Since this provider should not be run directly there it has no direct output. -The resulting data however is the wattage for the whole machine (AC Power) in Watts. +The resulting data however is the energy of the whole machine (AC Power) in micro Joules. This value has the same granularity as the one configured in the `config.yml` for the *CpuUtilizationProcfsSystemProvider* diff --git a/content/en/docs/measuring/metric-providers/rapl-container-msr.md b/content/en/docs/measuring/metric-providers/rapl-container-msr.md index 1877b34..55e15df 100644 --- a/content/en/docs/measuring/metric-providers/rapl-container-msr.md +++ b/content/en/docs/measuring/metric-providers/rapl-container-msr.md @@ -6,6 +6,10 @@ draft: true images: [] --- +{{< callout context="caution" icon="outline/alert-triangle" >}} +There is no such provider in the Green Metrics Tool. This page is only kept as a design note on the splitting approach. +{{< /callout >}} + In order to split the energy usage to the container level we use IC splitting. This is to be preferred over time splitting as outlined in this source for instance: diff --git a/content/en/docs/measuring/resource-limits.md b/content/en/docs/measuring/resource-limits.md index 8a12060..54f8714 100644 --- a/content/en/docs/measuring/resource-limits.md +++ b/content/en/docs/measuring/resource-limits.md @@ -14,7 +14,12 @@ GMT enables **and** enforces resource limits by: ## Understanding Auto-Assignment -When no resource limits are set GMT will determine how many available CPUs and how much memory is on the host sytem. +When no resource limits are set GMT will determine how many available CPUs and how much memory there are. + +Note that GMT does not look at the host system directly, but asks *Docker* what it has available +(`docker info` → `NCPU` and `MemTotal`). On a native Linux install these are identical to the host values. +Under Docker Desktop (macOS, Windows) however Docker runs in a VM and only sees the resources assigned to +that VM, so the values can be significantly lower than what the host has. ### CPUs @@ -30,7 +35,7 @@ Per default GMT will not reserve any memory from the host. This is fine for deve If you feel you want to change that check out [host resource reservations]({{< relref "/docs/cluster/host-resource-reservations" >}}). -Once a value is set, or the value is left at 0, GMT will calculate the total memory on the host system and deduct the configured memory reservation. +Once a value is set, or the value is left at 0, GMT will take the total memory that Docker reports (`docker info` → `MemTotal`) and deduct the configured memory reservation. Then all containers that have a manual `mem_limit` set will get their memory assigned. @@ -43,3 +48,29 @@ If during the process the memory gets exhausted because too much memory was requ You can see the auto applied values in the *Containers* Tab in the Dashboard
Dashboard Container Tab for GMT Measurements
+ +## Understanding Enforcement + +Once the values are determined GMT enforces them on every container it starts through these +`docker run` arguments: + +- `--cpuset-cpus` pins the containers to the cores `1` to *N*, whereas *N* is the number of assignable cores. + + Core `0` is therefore never available to your containers. It is the core that is reserved for GMT itself. + + If you reserve more than one core the additional cores are taken from the top of the range. + + Note that all containers are pinned to the *same* set of cores. Cores are not dedicated per container. +- `--cpus` limits the CPU time to the value of the `cpus` key of the service. +- `--memory` limits the memory to the value of the `mem_limit` key of the service. +- `--memory-swap` is set to the *same* value as `--memory`, which effectively disables swap for the container. + + This is intentional: a container that swaps would produce disk I/O and wildly skewed energy numbers instead of failing. +- `--oom-score-adj=1000` makes the containers the first candidates for the OOM killer, so that the host system and the metric providers survive an out-of-memory situation. +- `--env=GMT_CONTAINER_MEMORY_LIMIT=...` exposes the applied memory limit inside the container, so your application can size itself accordingly (e.g. a JVM heap or a DB buffer pool). + +Since swap is disabled and the OOM score is raised, a container that requests more memory than its limit +is killed rather than slowed down. GMT surfaces this as an error with exit code 137 and points you to the +`GMT_CONTAINER_MEMORY_LIMIT` variable. + +If you need to disable all of the above, for instance while developing locally, run with +`--dev-no-resource-limits`. Then no `--cpuset-cpus`, `--cpus`, `--memory`, `--memory-swap`, +`--oom-score-adj` and no `GMT_CONTAINER_MEMORY_LIMIT` are set at all and no auto-assignment happens. +Beware that this makes your measurements uncomparable to runs that had the limits applied. +See [runner.py switches →]({{< relref "runner-switches" >}}) for details. diff --git a/content/en/docs/measuring/runner-switches.md b/content/en/docs/measuring/runner-switches.md index c022080..b5050fa 100644 --- a/content/en/docs/measuring/runner-switches.md +++ b/content/en/docs/measuring/runner-switches.md @@ -10,33 +10,48 @@ Apart from the `config.yml` some additional configuration is possible when manua - `--name` A name which will be stored to the database to discern this run from others - `--uri` The URI to get the usage_scenario.yml from. - + If given a URL starting with `http(s)` the tool will try to clone a remote repository to `/tmp/green-metrics-tool/repo` - + If given a local directory starting with `/`, this will be used instead. + + If given a URL starting with `http://`, `https://`, `ssh://` or `git@` the tool will try to clone a remote repository to `/tmp/green-metrics-tool/repo` + + Any other value is treated as a local directory and must already exist. Both absolute and relative paths are supported. - `--branch` When providing a git repository, optionally specify a branch +- `--commit-hash` When providing a git repository, optionally specify a commit hash to check out - `--filename` An optional alternative filename if you do not want to use "usage_scenario.yml" + Multiple filenames can be provided, e.g. `--filename A.yml --filename B.yml` (both scenarios are executed sequentially) * Duplicated filenames are allowed (if you want to repeat the same file(s) multiple times, consider using `--iterations`) + Relative paths are supported, e.g. "../usage_scenario.yml" + Wildcard characters '\*' and '?' are supported, e.g. "*.yml" (all yml files in the current directory are executed sequentially) - `--variable` A key-value pair with a variable to be replaced in the [usage_scenario.yml →]({{< relref "usage-scenario" >}}) - + e.g.: `--variable '__GMT_VAR_MY_VALUE_=cats are cool'` + + e.g.: `--variable '__GMT_VAR_MY_VALUE__=cats are cool'` + + The name must match `__GMT_VAR_[\w]+__`, so note the two leading and the two trailing underscores + Can be used multiple times if more than one variable shall be submitted - `--iterations` Specify how many times each scenario should be executed (Default: 1) + With multiple files (see `--filename`), all files are processed sequentially, then the entire sequence is repeated N times * Example: with files A.yml, B.yml and `--iterations 2`, the execution order is A, B, A, B. +- `--carbon-simulation` The grid intensity to assume when running the job. + + Can be an integer, which will be applied to the whole run + + Can be a list of integers, which will be sent to *Elephant* + + Can be a UUID, which will be used as the simulation id for *Elephant* +- `--category` A category id to store for this run. Can be used multiple times if the run shall be in more than one category - `--commit-hash-folder` Use a different folder than the repository root to determine the commit hash for the run - `--user-id` Execute run as a specific user (Default: 1) - See also [User Management →]({{< relref "/docs/cluster/user-management.md" >}}) +- `--ssh-private-key` Path to a file on your system that holds an SSH private key. Needed to check out private repositories + + Please supply an SSH URL (`ssh://` or `git@`) in `--uri` when using a private key +- `--docker-credentials` Path to a JSON file with docker registry credentials, so that images from private registries can be pulled + + Format: `[{"registry":"...","username":"...","password":"..."}]` - `--config-override` Override the configuration file with the passed in yml file. - + Must be located in the same directory as the regular configuration file. Pass in only the name. + + Supply the full path. The file must end in `.yml`. - `--file-cleanup` flag to delete the metric provider data in `/tmp/green-metrics-tool`. Normally this folder is only purged on a new run start and files are left in `/tmp/green-metrics-tool`. - `--debug` flag to activate steppable debug mode + This allows you to enter the containers and debug them if necessary. - `--allow-unsafe` flag to activate unsafe volume bindings, ports, and complex env vars - + Arbitrary volume bindings into the containers. They are still read-only though + + Arbitrary volume bindings into the containers. The volume spec is handed to `docker run -v` as given, so **read-write mounts are possible**. Read-only is only enforced when running *without* this flag. + * See [usage_scenario.yml →]({{< relref "usage-scenario" >}}) **volumes** option for details + Port mappings to the host OS. * See [usage_scenario.yml →]({{< relref "usage-scenario" >}}) **ports** option for details + Non-Strict ENV vars mapped into container * See [usage_scenario.yml →]({{< relref "usage-scenario" >}}) **environment** option for details + + Non-Strict labels mapped into container + + Joining the Docker `host` network, which is otherwise restricted + + Bypasses the `allowed_run_args` allow list for **docker-run-args** - `--verbose-provider-boot` flag to boot metric providers gradually + This will enable the user to see the impact of each metric provider more clearly in the metric timelines + There will be a 10 second sleep after each provider boot @@ -46,13 +61,32 @@ Apart from the `config.yml` some additional configuration is possible when manua - `--print-phase-stats PHASE_NAME` Prints the stats of the given phase to the CLI. Typical argument would be "\[RUNTIME\]" to see all runtime phases combined - `--print-logs` Prints the container and process logs to stdout +#### Measurement settings + +These switches tune the timings and thresholds of a measurement run. All of them take an integer value. + +When running in cron / cluster-client mode these values are not taken from the CLI, but from the +[User Settings →]({{< relref "configuration#user-settings" >}}) of the user the run is mapped to. + +Beware that changing the durations and sleeps makes your runs uncomparable to runs measured with different values. + +- `--measurement-system-check-threshold` When to issue a warning and when to fail on system checks (Default: 3) + + Can be 1=INFO, 2=WARN or 3=ERROR. When set to 3 runs will fail only on errors, when 2 then also on warnings and when 1 also on pure info statements. +- `--measurement-pre-test-sleep` Sleep in seconds before the measurement starts (Default: 5) +- `--measurement-baseline-duration` Duration in seconds of the baseline phase (Default: 60) +- `--measurement-idle-duration` Duration in seconds of the idle phase (Default: 60) +- `--measurement-post-test-sleep` Sleep in seconds after the measurement has finished (Default: 5) +- `--measurement-phase-transition-time` Time in seconds that is waited between two phases (Default: 1) +- `--measurement-wait-time-dependencies` Max. time in seconds to wait for a `depends_on` dependency to become ready (Default: 60) +- `--measurement-flow-process-duration` Max. duration in seconds for how long one synchronous process in a flow may take. A Timeout-Exception is thrown if exceeded (Default: 86400) +- `--measurement-total-duration` Max. duration in seconds for how long the whole run may take, including building containers, baseline, idle, runtime and removal phases (Default: 86400) + #### Development switches without side effects These switches do not alter proper measurements, but might result in data not being generated. They can speed up runs by omitting non-critical checks or creation of optional data. -- `--skip-optimizations` Sjops the creation of potential optimization recommendations based on the measurement run. -- `--skip-system-checks` Skip checking the system if the GMT can run +- `--skip-optimizations` Skips the creation of potential optimization recommendations based on the measurement run. - `--skip-volume-inspect` Disable docker volume inspection. Can help if you encounter permission issues. - `--skip-download-dependencies` Skip downloading GMT dependencies like Kaniko etc. Useful to speed up runs if your dependencies are up to date. - `--skip-unsafe` flag to skip unsafe volume bindings, ports and complex env vars @@ -63,12 +97,15 @@ They can speed up runs by omitting non-critical checks or creation of optional d These switches may break or skew proper measurements or make them uncomparable due to missing info. However many of them are useful to speed up runs and aide in iterative development / debugging. +- `--dev-no-system-checks` Do not check the system if the GMT can run properly - `--dev-no-metrics` Skips loading the metric providers. Runs will be faster, but you will have no metric - `--dev-no-sleeps` Removes all sleeps. Resulting measurement data will be skewed. - `--dev-no-phase-stats` Do not calculate phase stats. -- `--dev-no-save` Will save no data to the DB. This implicitly activates `--dev-no-phase-stats`, `--dev-no-metrics` and `--dev-no-optimizations` +- `--dev-no-save` Will save no data to the DB. This implicitly activates `--dev-no-phase-stats`, `--dev-no-metrics` and `--skip-optimizations` - `--dev-no-container-dependency-collection` Do not collect container dependency information of started containers +- `--dev-no-resource-limits` Disable setting of resource limits per container. See [Resource Limits →]({{< relref "resource-limits" >}}) for what is skipped. - `--dev-cache-build` Checks if a container image is already in the local cache and will then not build it. Also doesn't clear the images after a run. Please note that skipping builds only works the second time you make a run since the image has to be built at least initially to work. +- `--dev-cache-repos` Do not clone the repository and the relations again, but use the ones already present on disk. Cannot be combined with `--file-cleanup`. - `--dev-stream-outputs` Stream the output of the container build and the called processes in flows and setup-commands to the terminal. Note that this disallows capturing of errors and build outputs in logs and error messages. - `--dev-flow-timetravel` Allows to repeat a failed flow or timetravel to beginning of flows. + Note that process logging, SCI calculations, and notes extraction may be incomplete in timetravel mode diff --git a/content/en/docs/measuring/usage-scenario.md b/content/en/docs/measuring/usage-scenario.md index ffb0348..7f71b90 100644 --- a/content/en/docs/measuring/usage-scenario.md +++ b/content/en/docs/measuring/usage-scenario.md @@ -8,11 +8,12 @@ weight: 415 The `usage_scenario.yml` consists of these main blocks: - Start of the file with some basic root level keys -- `services` - Handles the orchestration of containers +- `services` - (optional) Handles the orchestration of containers - `flow` - Handles the interaction with the containers - `compose-file` - (optional) A compose file to include - `relations` - (optional) Additional repositories to check out - `networks` - (optional) Handles the orchestration of networks +- `volumes` - (optional) Named volumes to inspect the size of - `custom_metrics` - (optional) Handles Custom Metrics and SCI Its format is an extended subset of the [Docker Compose Specification](https://docs.docker.com/compose/compose-file/), which means that we keep the same format, but disallow some options and also add some exclusive options to our tool. However, keys that have the same name are also identical in function - thought potentially with some limitations. @@ -34,9 +35,11 @@ description: This is just an example usage_scenario ... - `name` **[str]**: Name of the scenario - `description` **[str]**: Detailed description of the scenario - `author` **[str]**: Author of the scenario -- `architecture` **[str]** *(optional)*: If your *usage_scenario* runs only on a specific architecture you can instruct the GMT to check if the architecture of the machine matches. You can specify **Linux**, **Windows** and **Darwin**. Omit this key if your scenario has no architecture restriction. +- `architecture` **[str]** *(optional)*: If your *usage_scenario* runs only on a specific architecture you can instruct the GMT to check if the architecture of the machine matches. You can specify **Linux**, **Windows** and **macOS**. Omit this key if your scenario has no architecture restriction. + + The value is compared case-insensitively. Note that macOS must be given as **macOS** and not as *Darwin*, otherwise the check will always fail. + Note: Windows with WSL2 and Linux containers would be **Linux** as architecture - `ignore-unsupported-compose` **[bool]** *(optional)*: Ignore unsupported [Docker Compose](https://docs.docker.com/compose/compose-file) features and still run usage_scenario +- `version` **[str|int|float]** *(optional)*: Part of the Docker Compose specification. Accepted, but ignored by GMT as it is non-functional. Please note that when running the measurement you can supply an additional name, which can and should be different from the name in the `usage_scenario.yml`. @@ -63,15 +66,19 @@ services: setup-commands: - command: sleep 20 volumes: - - /LOCAL/PATH:/PATH/IN/CONTAINER + - /LOCAL/PATH:/PATH/IN/CONTAINER:ro networks: - wordpress-mariadb-data-green-coding-network + mem_limit: 2G + cpus: 2 + shm_size: 256M healthcheck: test: curl -f http://nc interval: "30s" timeout: "10s" retries: 10 start_period: "10s" + start_interval: "5s" disable: False gcb-wordpress-apache: # ... @@ -84,16 +91,22 @@ services: - gcb-wordpress-mariadb ``` -- `services` **[dict]**: (Dictionary of container dictionaries for orchestration) +- `services` **[dict]** *(optional)*: (Dictionary of container dictionaries for orchestration) + + A `usage_scenario.yml` without `services` is valid. This is the case when you want to benchmark containers that are already running on your host. + `[CONTAINER]:` **[a-zA-Z0-9_]** The name of the container/service + `image:` **[str]** Docker image identifier. If `build` is not provided the image needs to be accessible locally on Docker Hub. If `build` is provided it is used as identifier for the image. + `build:` **[str]** *(optional)* Path to build context. See `context` for restrictions. Default for `dockerfile` is `Dockerfile`. Alternatively, you can provide more detailed build information with: - `context:` **[str]** *(optional)* Path to the build context. Needs to be in the path or repo that is passed with `--uri` to `runner.py`. Default: `.`. - `dockerfile:` **[str]** *(optional)* Path to Dockerfile. Needs to be in `context`. Default: `Dockerfile`. + - `args:` **[list]** *(optional)* Build arguments that are passed to the build as `--build-arg`. Supply them as a list of single key-value dictionaries, e.g. a list item in the format: *- MY_ARG: my_value*. The other forms of the *Docker Compose Specification* (a plain dict, or list items in the format *- MY_ARG=my_value*) are currently not supported. + `container_name:` **[a-zA-Z0-9_]** *(optional)* With this key you can overwrite the name of the container. If not given, the defined service name above is used as the name of the container. + `environment:` **[dict|list]** *(optional)* - Either Key-Value pairs for ENV variables inside the container - Or list items with strings in the format: *MYSQL_PASSWORD=123* + + `labels:` **[dict|list]** *(optional)* + - Either Key-Value pairs for Docker labels set on the container + - Or list items with strings in the format: *my.label=123* + - Without `--allow-unsafe` the key must match `^[A-Za-z_]+[A-Za-z0-9_.]*$` and the value may be at most 1024 characters long + `ports:` **[int:int]** *(optional)* - Docker container portmapping on host OS to be used with `--allow-unsafe` flag. + `init:` **[boolean]** @@ -107,13 +120,22 @@ services: - List of commands to be run before actual load testing. Mostly installs will be done here. Note that your docker container must support these commands and you cannot rely on a standard linux installation to provide access to /bin - `command:` **[str]** * The command to be executed + - `detach:` **[bool]** *(optional, default: `false`)* + * When the command is detached it will get sent to the background and the setup will continue with the next command. The process is terminated at the end of the run. - `shell:` **[str]** *(optional)* * Will execute the `setup-commands` in a shell. Use this if you need shell-mechanics like redirection `>` or chaining `&&`. ** Please use a string for a shell command here like `sh`, `bash`, `ash` etc. The shell must be available in your container - `volumes:` **[list]** *(optional)* - - List of volumes to be mapped. Only read if `runner.py` is executed with `--allow-unsafe` flag - - `networks:` **[list]** *(optional)* + - List of volumes to be mapped in the format `source:target[:ro]`. + - This key is always read. The `--allow-unsafe` flag does not gate it, but *relaxes* how it is handled: + * In **safe mode** (the default) only read-only mounts are allowed, so the `:ro` (or `:readonly`) option is mandatory, and the source is resolved relative to the folder of your `usage_scenario.yml`. An exception are mounts that are listed in the `allowed_volume_mounts` capability of your user, which may be read-write and may be absolute paths or named volumes. + * With **`--allow-unsafe`** the volume spec is handed to `docker run -v` as given, so read-write mounts and absolute host paths are possible. + - Note that `--skip-unsafe` has no effect on volumes. It only applies to `ports`, `environment` and `labels`. + - `networks:` **[list|dict]** *(optional)* - The networks to put the container into. If no networks are defined throughout the `usage_scenario.yml` the container will be put into the default network will all others in the file. + - When given as a dict you can supply network modifiers per network: + * `aliases:` **[list]** *(optional)* Additional DNS names the container is reachable under inside that network + - Joining the Docker `host` network is restricted and needs `--allow-unsafe` - `healthcheck:` **[dict]** *(optional)* - Please see the definition of these arguments and how healthcheck works in the official docker compose definition. We just copy them over: [Docker compose healthcheck specification](https://docs.docker.com/compose/compose-file/compose-file-v3/#healthcheck) - `test:` **[str|list]** @@ -121,16 +143,18 @@ services: - `timeout:` **[str]** - `retries:` **[integer]** - `start_period:` **[str]** + - `start_interval:` **[str]** Time between health checks during the *start period* - `disable:` **[boolean]** - `folder-destination`: **[str]** *(optional)* - Specify where the project that is being measured will be mounted inside of the container - Defaults to `/tmp/repo` - - `command:` **[str]** *(optional)* + - `command:` **[str|list]** *(optional)* - Command to be executed when container is started. When container does not have a daemon running typically a shell is started here to have the container running like `bash` or `sh`. - - `entrypoint:` **[str]** *(optional)* + - Can be given as a string, which is split shell-like, or as a list of arguments. + - `entrypoint:` **[str|list]** *(optional)* - Declares the default entrypoint for the service container. This overrides the ENTRYPOINT instruction from the service's Dockerfile. - - The value of `entrypoint` can either be an empty string (ENTRYPOINT instruction will be ignored) or a single word (helpful to provide a script). - - If you need an entrypoint that consists of multiple commands/arguments, either provide a script (e.g. `entrypoint.sh`) or set it to an empty string and provide your commands via `command`. + - The value of `entrypoint` can be an empty string (ENTRYPOINT instruction will be ignored), a string, or a list of arguments. + - When a string is given it is split shell-like. The first element becomes the entrypoint, all remaining elements are prepended to `command`. - `log-stdout:` **[boolean]** *(optional, default: `true`)* - Will log the *stdout* of the container and make it available through the frontend in the *Logs* tab. - Please see the [Best Practices →]({{< relref "best-practices" >}}) for when to disable the logging. @@ -144,11 +168,30 @@ services: - Format specification is documented below in section [Read-notes-stdout format specification →]({{< relref "#read-notes-stdout-format-specification" >}}). - `docker-run-args:` **[list]** *(optional)* - A list of string that should be added to the `docker run` command of that container. - - The argument needs to be listed in the `user.capabilities` json under `measurement:orchestrators:docker:allow-args`. The string in the `user.capabilities` can be a regex. Opening this up could be a potential security issue! + - The argument needs to be listed in the `user.capabilities` json under `measurement:orchestrators:docker:allowed_run_args`. The string in the `user.capabilities` can be a regex and must match the whole argument. Opening this up could be a potential security issue! + - Running with `--allow-unsafe` bypasses this allow list entirely and every argument is accepted. + - `mem_limit:` **[str|int]** *(optional)* + - The memory limit of the container, e.g. `2G`. If not set, GMT auto-assigns a value. + - Can also be given as `deploy.resources.limits.memory`. If both are given they must be identical. + - `cpus:` **[str|int|float]** *(optional)* + - The number of CPUs the container may use. If not set, GMT auto-assigns all assignable cores. + - Can also be given as `deploy.resources.limits.cpus`. If both are given they must be identical. + - `shm_size:` **[str|int]** *(optional)* + - Size of `/dev/shm` for the container, passed to `docker run --shm-size`. + - `restart:` **[str]** *(optional)* + - Part of the Docker Compose specification. Accepted, but ignored, as GMT does its own orchestration. + - `expose:` **[list]** *(optional)* + - Part of the Docker Compose specification. Accepted, but ignored, as it is non-functional. Please note that every key below `services` will serve as the name of the container later on. You can overwrite the container name with the key `container_name`. +Also see [Resource Limits →]({{< relref "resource-limits" >}}) for how `mem_limit` and `cpus` are +auto-assigned and enforced. + +The `cmd` key is not supported anymore. If your file still uses it you will get an error asking you +to migrate to `command`. + ### Relations ```yml @@ -190,11 +233,40 @@ Example: ```yaml networks: - name: wordpress-mariadb-data-green-coding-network + wordpress-mariadb-data-green-coding-network: + gmt-test-network: + internal: true ``` -- `networks:` **[dict]** (Dictionary of network dictionaries for orchestration) - + `name: [NETWORK]` **[a-zA-Z0-9_]** The name of the network with a trailing colon. No value required. +- `networks:` **[dict|list]** (Dictionary of network dictionaries for orchestration, or a plain list of network names) + + `[NETWORK]:` **[a-zA-Z0-9_-]** The key is the name of the network. No value is required. + - `internal:` **[bool]** *(optional)* Creates the network with `--internal`, so containers in it have no external connectivity. + + The pre-defined Docker networks `host`, `bridge` and `none` cannot be created here. They already exist and can only be joined. + +Networks defined here are created before the containers are started and are removed again after the run. +Put a container into a network with the `networks` key of the service. + +### Volumes + +Example: + +```yaml +volumes: + my-named-volume: +``` + +- `volumes:` **[dict|str]** *(optional)* (Dictionary of named volumes, or a single volume name) + + `[VOLUME]:` **[a-zA-Z0-9_-]** The key is the name of the volume. No value is required. + +Contrary to the *Docker Compose Specification* GMT does **not** create named volumes from this key. +The volume must already exist on the machine. GMT only inspects the listed volumes and reports their +size as *Container Volume Sizes* in the *Machine* tab of the Dashboard. + +The inspection only runs when all of the following are true: + +- `runner.py` is executed with `--allow-unsafe` (volume information reveals host filesystem paths) +- `--skip-volume-inspect` is **not** set +- the run is on Linux (the inspection is skipped on macOS and Windows) ### Flow @@ -220,7 +292,7 @@ flow: container: database-container commands: - type: console - command: killall postgres + command: killall postgres ``` - `flow:` **[list]** (List of flows to interact with containers) diff --git a/content/en/docs/prologue/example-applications.md b/content/en/docs/prologue/example-applications.md index af48636..ed07577 100644 --- a/content/en/docs/prologue/example-applications.md +++ b/content/en/docs/prologue/example-applications.md @@ -29,7 +29,7 @@ Please check out our [repository of example applications on GitHub](https://gith ## Demoing the example application (optional) ```bash -docker compose +docker compose up ``` See in the `README.md` where to view output if present and how to trigger the application. diff --git a/content/en/docs/prologue/philosophy-methodology.md b/content/en/docs/prologue/philosophy-methodology.md index 0e682c5..2c4c3f3 100644 --- a/content/en/docs/prologue/philosophy-methodology.md +++ b/content/en/docs/prologue/philosophy-methodology.md @@ -46,8 +46,9 @@ Such splittings can be theoretically done as for instance [Scaphandre](https://g These values, although theoretically intriguing, have multiple caveats attached like for instance speculative execution, out of order execution, instable instruction counting etc. that make the non-exact and still only an approximation to what the process / container is actually in energy. - Therefore we decided for the moment of not going the route of splitting the energy per container for the moment until a gold-standard has emerged that makes sense to use. - Our philosphy is rather that if a machine is executing a piece of software everything on that box should be attributed to the energy cost of the software. + Because of these caveats we do not treat any per-container value as a ground truth. Our philosphy is rather that if a machine is executing a piece of software everything on that box should be attributed to the energy cost of the software, and the machine-wide value therefore stays our headline number. + + On top of that we do offer a per-container drill-down, which splits the machine energy proportionally to each container's CPU utilization share. We report it *in addition to* the machine-wide value and label it explicitly as an estimation. It is opt-in in the sense that it requires a PSU as well as a system-level and a container-level CPU utilization [Metric Provider →]({{< relref "/docs/measuring/metric-providers" >}}) to be activated. See [Estimating Containers →]({{< relref "/docs/measuring/measuring-containers" >}}) for the exact splitting method and its limitations. Our Measurement Cluster uses dedicated machines so small that they represent a typical VM that you would also use in the cloud to give a realistic and comparable picture of what your software might also be using in a final cloud setup. Furthermore we will offer soon the support to for instance separate two logical and physical disjunct components onto two machines.