Skip to content

Commit

Permalink
Monitor: show time info
Browse files Browse the repository at this point in the history
  • Loading branch information
paugier committed Apr 19, 2024
1 parent c52720f commit 42b4f1b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/fluidimage/executors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ class ExecutorBase(ABC):
path_job_data: Path
_path_lockfile: Path
num_expected_results: int
time_start: str

def _init_log_path(self):
unique_postfix = f"{time_as_str()}_{os.getpid()}"
self.time_start_str = time_as_str()
unique_postfix = f"{self.time_start_str}_{os.getpid()}"
path_job_data = self.path_dir_result / f"job_{unique_postfix}"

if path_job_data.exists():
Expand Down Expand Up @@ -229,6 +231,7 @@ def _init_compute_log(self):
"nb_max_workers": self.nb_max_workers,
"path_dir_result": self.path_dir_result,
"num_expected_results": self.num_expected_results,
"time_start": self.time_start_str,
}

def _save_lock_file(self):
Expand All @@ -250,6 +253,9 @@ def _save_lock_file(self):
def _release_lock(self):
if self._path_lockfile.exists():
self._path_lockfile.unlink(missing_ok=True)
t_as_str = time_as_str()
path_end_time = self._path_lockfile.with_name("time_end.txt")
path_end_time.write_text(f"{t_as_str}\n")

def _save_job_data(self):
self.path_job_data = self.path_dir_result / f"job_{self._unique_postfix}"
Expand Down
3 changes: 3 additions & 0 deletions src/fluidimage/executors/exec_async_seq_for_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import trio

from fluiddyn import time_as_str

from .exec_async_sequential import ExecutorAsyncSequential


Expand Down Expand Up @@ -78,6 +80,7 @@ def _init_log_path(self):
self.path_dir_exceptions = Path(self._log_path).parent

def _init_compute(self):
self.time_start_str = time_as_str()
self._init_compute_log()
if hasattr(self, "_path_results"):
self._path_results.touch()
Expand Down
53 changes: 53 additions & 0 deletions src/fluidimage/gui/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import argparse
import os
import subprocess
from datetime import datetime
from importlib import import_module
from pathlib import Path

Expand Down Expand Up @@ -52,6 +53,15 @@ def copy_doc(params_node, params_node_with_doc):
copy_doc(params_node[tag], params_node_with_doc[tag])


def format_time_in_seconds(duration_in_s):
"""return a formatted str of the duration"""
if duration_in_s < 60:
return f"{duration_in_s:.2f} s"
hours, remainder = divmod(duration_in_s, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}"


class MonitorApp(App):
"""Fluidimage monitor Textual app"""

Expand All @@ -60,6 +70,8 @@ class MonitorApp(App):
timer_update_info: Timer
digit_num_results: Digits
widget_doc: Markdown
label_is_running: Label
label_times: Label
job_is_running: bool

CSS_PATH = "monitor.tcss"
Expand Down Expand Up @@ -126,6 +138,8 @@ def __init__(self, args):
return

self.path_lockfile = self.path_job_info / "is_running.lock"
self.path_time_end = self.path_job_info / "time_end.txt"
self.time_end = None
self.check_is_running()

self.path_info = self.path_job_info / "info.xml"
Expand All @@ -134,6 +148,10 @@ def __init__(self, args):
key: info[key] for key in sorted(info._get_key_attribs())
}

self.time_start = datetime.strptime(
self.info_job["time_start"], "%Y-%m-%d_%H-%M-%S"
)

self.params = ParamContainer(path_file=self.path_job_info / "params.xml")

module_name, class_name = self.info_job["topology"].rsplit(".", 1)
Expand Down Expand Up @@ -176,6 +194,10 @@ def compose(self) -> ComposeResult:
f"Running: {self.job_is_running}"
)
yield self.label_is_running
self.label_times = Label(
self.compute_times_str(), id="label_times"
)
yield self.label_times
yield Rule()
yield DataTable()
yield Rule()
Expand Down Expand Up @@ -251,6 +273,37 @@ def update_info(self):
if not self.check_is_running():
self.timer_update_info.pause()
self.label_is_running.update(f"Running: {self.job_is_running}")
self.label_times.update(self.compute_times_str())

def load_time_max(self):
"""Load the end time or now"""
if self.time_end is not None:
return self.time_end

if self.path_time_end.exists():
self.time_end = datetime.strptime(
self.path_time_end.read_text().strip(), "%Y-%m-%d_%H-%M-%S"
)
return self.time_end
else:
return datetime.now()

def compute_times_str(self):
"""Compute the string used for the label 'label_times'"""

duration = self.load_time_max() - self.time_start
duration_in_s = duration.total_seconds()
duration_str = format_time_in_seconds(duration_in_s)

if self.job_is_running:
result = f"Started since {duration_str}"
else:
result = f"Total duration: {duration_str}"

if self.num_results:
result += f" ({duration_in_s * self.info_job['nb_max_workers'] / self.num_results:.2f} s.CPU/result)"

return result

def action_launch_fluidpivviewer(self) -> None:
"""Launch fluidpivviewer from the result directory"""
Expand Down

0 comments on commit 42b4f1b

Please sign in to comment.