@@ -317,6 +317,7 @@ def __init__(
317317 self ._task_stop_measurement_values = {}
318318 self ._tasks : Dict [str , Task ] = {}
319319 self ._active_task : Optional [str ] = None
320+ self ._active_task_emissions_at_start : Optional [EmissionsData ] = None
320321
321322 # Tracking mode detection
322323 ressource_tracker = ResourceTracker (self )
@@ -474,7 +475,7 @@ def start_task(self, task_name=None) -> None:
474475 self ._scheduler_monitor_power .start ()
475476
476477 if self ._active_task :
477- logger .info ("A task is already under measure" )
478+ logger .warning ("A task is already under measure" )
478479 return
479480 if not task_name :
480481 task_name = uuid .uuid4 ().__str__ ()
@@ -484,8 +485,13 @@ def start_task(self, task_name=None) -> None:
484485 # Read initial energy for hardware
485486 for hardware in self ._hardware :
486487 hardware .start ()
487- _ = self ._prepare_emissions_data ()
488- _ = self ._compute_emissions_delta (_ )
488+ prepared_data_for_task_start = self ._prepare_emissions_data ()
489+ self ._active_task_emissions_at_start = dataclasses .replace (
490+ prepared_data_for_task_start
491+ )
492+ # The existing call to _compute_emissions_delta uses the result of _prepare_emissions_data.
493+ # Let's make sure it uses the same one we captured.
494+ self ._compute_emissions_delta (prepared_data_for_task_start )
489495
490496 self ._tasks .update (
491497 {
@@ -506,20 +512,51 @@ def stop_task(self, task_name: str = None) -> EmissionsData:
506512 self ._scheduler_monitor_power .stop ()
507513
508514 task_name = task_name if task_name else self ._active_task
515+ if self ._tasks .get (task_name ) is None :
516+ logger .warning ("stop_task : No active task to stop." )
517+ return None
509518 self ._measure_power_and_energy ()
519+ emissions_data = (
520+ self ._prepare_emissions_data ()
521+ ) # This is emissions_data_at_stop
522+
523+ if self ._active_task_emissions_at_start is None :
524+ logger .error (
525+ f"Task { task_name } : _active_task_emissions_at_start was None. "
526+ "This indicates an issue, possibly start_task was not called or was corrupted. "
527+ "Reporting zero delta for this task to avoid errors."
528+ )
529+ emissions_data_delta = dataclasses .replace (emissions_data )
530+ # Zero out energy fields for the delta
531+ emissions_data_delta .emissions = 0.0
532+ emissions_data_delta .emissions_rate = 0.0
533+ emissions_data_delta .cpu_energy = 0.0
534+ emissions_data_delta .gpu_energy = 0.0
535+ emissions_data_delta .ram_energy = 0.0
536+ emissions_data_delta .energy_consumed = 0.0
537+ else :
538+ emissions_data_delta = dataclasses .replace (emissions_data )
539+ emissions_data_delta .compute_delta_emission (
540+ self ._active_task_emissions_at_start
541+ )
510542
511- emissions_data = self . _prepare_emissions_data ()
512- emissions_data_delta = self ._compute_emissions_delta (emissions_data )
543+ # Update global _previous_emissions state using the current totals at task stop.
544+ self ._compute_emissions_delta (emissions_data )
513545
514546 task_duration = Time .from_seconds (
515547 time .perf_counter () - self ._tasks [task_name ].start_time
516548 )
517549
550+ # task_emission_data is the final delta object to be returned and stored
518551 task_emission_data = emissions_data_delta
519- task_emission_data .duration = task_duration .seconds
552+ task_emission_data .duration = (
553+ task_duration .seconds
554+ ) # Set the correct duration for the task
555+
520556 self ._tasks [task_name ].emissions_data = task_emission_data
521557 self ._tasks [task_name ].is_active = False
522558 self ._active_task = None
559+ self ._active_task_emissions_at_start = None # Clear task-specific start data
523560
524561 return task_emission_data
525562
@@ -625,7 +662,8 @@ def _persist_data(
625662
626663 def _prepare_emissions_data (self ) -> EmissionsData :
627664 """
628- :delta: If 'True', return only the delta comsumption since the last call.
665+ Prepare the emissions data to be sent to the API or written to a file.
666+ :return: EmissionsData object with the total emissions data.
629667 """
630668 cloud : CloudMetadata = self ._get_cloud_metadata ()
631669 duration : Time = Time .from_seconds (time .perf_counter () - self ._start_time )
@@ -688,9 +726,14 @@ def _prepare_emissions_data(self) -> EmissionsData:
688726 return total_emissions
689727
690728 def _compute_emissions_delta (self , total_emissions : EmissionsData ) -> EmissionsData :
691- delta_emissions : EmissionsData = total_emissions
729+ """
730+ Compute the delta emissions since the last call to this method.
731+ :param total_emissions: The total emissions data to compute the delta from.
732+ :return: EmissionsData with the delta emissions.
733+ """
692734 if self ._previous_emissions is None :
693735 self ._previous_emissions = total_emissions
736+ delta_emissions : EmissionsData = total_emissions
694737 else :
695738 # Create a copy
696739 delta_emissions = dataclasses .replace (total_emissions )
0 commit comments