cli: refactor progress indication
[deliverable/lttng-analyses.git] / lttnganalyses / cli / progressbar.py
index cd30d4e31d3b9cb634117ec961040e280453d893..b7938e9d5dcd4531cf075d3f7c092ee49e4e9c90 100644 (file)
 
 import os
 import sys
+import time
 from . import mi
 from collections import namedtuple
+from ..common import format_utils
+
 
 try:
     from progressbar import ETA, Bar, Percentage, ProgressBar
@@ -31,8 +34,9 @@ try:
 except ImportError:
     progressbar_available = False
 
+
 # approximation for the progress bar
-BYTES_PER_EVENT = 30
+_BYTES_PER_EVENT = 30
 
 
 def get_folder_size(folder):
@@ -46,85 +50,106 @@ def get_folder_size(folder):
     return total_size
 
 
-def _get_maxval(obj):
-    size = get_folder_size(obj._args.path)
+class _Progress:
+    def __init__(self, ts_begin, ts_end, path, use_size=False):
+        if ts_begin is None or ts_end is None or use_size:
+            size = get_folder_size(path)
+            self._maxval = size / _BYTES_PER_EVENT
+            self._use_time = False
+        else:
+            self._maxval = ts_end - ts_begin
+            self._ts_begin = ts_begin
+            self._ts_end = ts_end
+            self._use_time = True
 
-    return size / BYTES_PER_EVENT
+        self._at = 0
+        self._event_count = 0
+        self._last_event_count_check = 0
+        self._last_time_check = time.time()
 
+    def update(self, event):
+        self._event_count += 1
 
-def progressbar_setup(obj):
-    if obj._args.no_progress:
-        obj.pbar = None
-        return
+        if self._use_time:
+            self._at = event.timestamp - self._ts_begin
+        else:
+            self._at = self._event_count
 
-    if progressbar_available:
-        widgets = ['Processing the trace: ', Percentage(), ' ',
-                   Bar(marker='#', left='[', right=']'),
-                   ' ', ETA(), ' ']  # see docs for other options
-        obj.pbar = ProgressBar(widgets=widgets,
-                               maxval=_get_maxval(obj))
-        obj.pbar.start()
-    else:
-        print('Warning: progressbar module not available, '
-              'using --no-progress.', file=sys.stderr)
-        obj._args.no_progress = True
-        obj.pbar = None
-    obj.event_count = 0
+        if self._at > self._maxval:
+            self._at = self._maxval
 
+        if self._event_count - self._last_event_count_check >= 101:
+            self._last_event_count_check = self._event_count
+            now = time.time()
 
-def progressbar_update(obj):
-    if obj._args.no_progress or obj.pbar is None:
-        return
+            if now - self._last_time_check >= .1:
+                self._update_progress()
+                self._last_time_check = now
 
-    try:
-        obj.pbar.update(obj.event_count)
-    except ValueError:
+    def _update_progress(self):
         pass
-    obj.event_count += 1
 
+    def finalize(self):
+        pass
 
-def progressbar_finish(obj):
-    if obj._args.no_progress:
-        return
-    obj.pbar.finish()
 
+class FancyProgressBar(_Progress):
+    def __init__(self, ts_begin, ts_end, path, use_size):
+        super().__init__(ts_begin, ts_end, path, use_size)
+        self._pbar = None
 
-class _MiProgress:
-    def __init__(self, maxval):
-        self._maxval = maxval
-        self._events = 0
-        self._step = maxval // 997
+        if progressbar_available:
+            widgets = ['Processing the trace: ', Percentage(), ' ',
+                       Bar(marker='#', left='[', right=']'),
+                       ' ', ETA(), ' ']  # see docs for other options
+            self._pbar = ProgressBar(widgets=widgets,
+                                   maxval=self._maxval)
+            self._pbar.start()
+        else:
+            print('Warning: progressbar module not available, '
+                  'using --no-progress.', file=sys.stderr)
 
-        if self._step == 0:
-            self._step = 1
+    def _update_progress(self):
+        if self._pbar is None:
+            return
 
-    def init(self):
-        msg = 'Starting analysis: {} estimated events'.format(round(self._maxval))
-        mi.print_progress(0, msg)
+        self._pbar.update(self._at)
 
-    def update(self):
-        if (self._events % self._step) == 0:
-            if self._events > self._maxval:
-                mi.print_progress(1, 'Almost done...')
-            else:
-                at = round(self._events / self._maxval, 4)
-                msg = '{} events processed'.format(self._events)
-                mi.print_progress(at, msg)
+    def finalize(self):
+        if self._pbar is None:
+            return
 
-        self._events += 1
+        self._pbar.finish()
 
-    def finish(self):
-        mi.print_progress(1, 'Done!')
 
+class MiProgress(_Progress):
+    def __init__(self, ts_begin, ts_end, path, use_size):
+        super().__init__(ts_begin, ts_end, path, use_size)
+
+        if self._use_time:
+            fmt = 'Starting analysis from {} to {}'
+            begin = format_utils.format_timestamp(self._ts_begin)
+            end = format_utils.format_timestamp(self._ts_end)
+            msg = fmt.format(begin, end)
+        else:
+            msg = 'Starting analysis: {} estimated events'.format(round(self._maxval))
 
-def mi_progress_setup(obj):
-    obj.pbar = _MiProgress(_get_maxval(obj))
-    obj.pbar.init()
+        mi.print_progress(0, msg)
 
+    def _update_progress(self):
+        if self._at == self._maxval:
+            mi.print_progress(1, 'Done!')
+            return
 
-def mi_progress_update(obj):
-    obj.pbar.update()
+        if self._use_time:
+            ts_at = self._at + self._ts_begin
+            at_ts = format_utils.format_timestamp(ts_at)
+            end = format_utils.format_timestamp(self._ts_end)
+            msg = '{}/{}; {} events processed'.format(at_ts, end, self._event_count)
+        else:
+            msg = '{} events processed'.format(self._event_count)
 
+        mi.print_progress(round(self._at / self._maxval, 4), msg)
 
-def mi_progress_finish(obj):
-    obj.pbar.finish()
+    def finalize(self):
+        mi.print_progress(1, 'Done!')
This page took 0.026953 seconds and 5 git commands to generate.