diff --git a/codecarbon/cli/main.py b/codecarbon/cli/main.py index 32c78f58..b5f60330 100644 --- a/codecarbon/cli/main.py +++ b/codecarbon/cli/main.py @@ -1,4 +1,5 @@ import os +import signal import sys import time from pathlib import Path @@ -23,7 +24,7 @@ ) from codecarbon.core.api_client import ApiClient, get_datetime_with_timezone from codecarbon.core.schemas import ExperimentCreate, OrganizationCreate, ProjectCreate -from codecarbon.emissions_tracker import EmissionsTracker +from codecarbon.emissions_tracker import EmissionsTracker, OfflineEmissionsTracker AUTH_CLIENT_ID = os.environ.get( "AUTH_CLIENT_ID", @@ -336,28 +337,55 @@ def monitor( api: Annotated[ bool, typer.Option(help="Choose to call Code Carbon API or not") ] = True, + offline: Annotated[bool, typer.Option(help="Run in offline mode")] = False, + country_iso_code: Annotated[ + str, typer.Option(help="3-letter country ISO code for offline mode") + ] = None, + region: Annotated[ + str, typer.Option(help="Region/province for offline mode") + ] = None, ): - """Monitor your machine's carbon emissions. + """Monitor your machine's carbon emissions.""" + if offline: + if not country_iso_code: + print( + "ERROR: country_iso_code is required for offline mode", file=sys.stderr + ) + raise typer.Exit(1) - Args: - measure_power_secs (Annotated[int, typer.Argument, optional): Interval between two measures. Defaults to 10. - api_call_interval (Annotated[int, typer.Argument, optional): Number of measures before calling API. Defaults to 30. - api (Annotated[bool, typer.Option, optional): Choose to call Code Carbon API or not. Defaults to True. - """ - experiment_id = get_existing_local_exp_id() - if api: - if experiment_id is None: + tracker = OfflineEmissionsTracker( + measure_power_secs=measure_power_secs, + country_iso_code=country_iso_code, + region=region, + ) + else: + experiment_id = get_existing_local_exp_id() + if api and experiment_id is None: print( "ERROR: No experiment id, call 'codecarbon config' first.", file=sys.stderr, ) + raise typer.Exit(1) + + tracker = EmissionsTracker( + measure_power_secs=measure_power_secs, + api_call_interval=api_call_interval, + save_to_api=api, + ) + + def signal_handler(signum, frame): + print("\nReceived signal to stop. Saving emissions data...") + tracker.stop() + sys.exit(0) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + print("CodeCarbon is going in an infinite loop to monitor this machine.") - with EmissionsTracker( - measure_power_secs=measure_power_secs, - api_call_interval=api_call_interval, - save_to_api=api, - ) as tracker: - # Infinite loop + print("Press Ctrl+C to stop and save emissions data.") + + tracker.start() + try: while True: if ( hasattr(tracker, "_another_instance_already_running") @@ -366,6 +394,10 @@ def monitor( print("Another instance of CodeCarbon is already running. Exiting.") break time.sleep(300) + except Exception as e: + print(f"\nError occurred: {e}") + tracker.stop() + raise e def questionary_prompt(prompt, list_options, default): diff --git a/docs/edit/usage.rst b/docs/edit/usage.rst index ca09f43b..ce2634ae 100644 --- a/docs/edit/usage.rst +++ b/docs/edit/usage.rst @@ -15,17 +15,17 @@ Command line ~~~~~~~~~~~~ -Create a minimal configuration file (just follow the prompts) : +Create a minimal configuration file (just follow the prompts) : .. code-block:: console - codecarbon config + codecarbon config .. image:: https://asciinema.org/a/667970.svg :align: center :alt: Init config :target: https://asciinema.org/a/667970 - + You can use the same command to modify an existing config : .. image:: https://asciinema.org/a/667971.svg @@ -38,12 +38,12 @@ If you want to track the emissions of a computer without having to modify your c .. code-block:: console - codecarbon monitor + codecarbon monitor You have to stop the monitoring manually with ``Ctrl+C``. -In the following example you will see how to use the CLI to monitor all the emissions of you computer and sending everything -to an API running on "localhost:8008" (Or you can start a private local API with "docker-compose up"). Using the public API with +In the following example you will see how to use the CLI to monitor all the emissions of you computer and sending everything +to an API running on "localhost:8008" (Or you can start a private local API with "docker-compose up"). Using the public API with this is not supported yet (coming soon!) .. image:: https://asciinema.org/a/667984.svg @@ -52,6 +52,11 @@ this is not supported yet (coming soon!) :target: https://asciinema.org/a/667984 +The command line could also works without internet by providing the country code like this: + +.. code-block:: console + + codecarbon monitor --offline --country-iso-code FRA Implementing CodeCarbon in your code allows you to track the emissions of a specific block of code.