1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2025-03-04 10:39:50 +00:00

enhance JSON progress information

separate output types, extra information
This commit is contained in:
Marian Beermann 2017-02-27 20:30:20 +01:00
parent 7c9c4b61d7
commit 6288c9f751
2 changed files with 76 additions and 15 deletions

View file

@ -39,6 +39,33 @@ archive_progress
path
Current path
progress_message
A message-based progress information with no concrete progress information, just a message
saying what is currently worked on.
operation
integer ID of the operation
finished
boolean indicating whether the operation has finished, only the last object for an *operation*
can have this property set to *true*.
message
current progress message (may be empty/absent)
progress_percent
Absolute progress display with defined end/total and current value.
operation
integer ID of the operation
finished
boolean indicating whether the operation has finished, only the last object for an *operation*
can have this property set to *true*.
message
A formatted progress message, this will include the percentage and perhaps other information
current
Current value (always less-or-equal to *total*)
total
Total value
file_status
This is only output by :ref:`borg_create` and :ref:`borg_recreate` if ``--list`` is specified. The usual
rules for the file listing applies, including the ``--filter`` option.

View file

@ -1377,10 +1377,20 @@ def ellipsis_truncate(msg, space):
class ProgressIndicatorBase:
LOGGER = 'borg.output.progress'
JSON_TYPE = None
json = False
operation_id_counter = 0
@classmethod
def operation_id(cls):
cls.operation_id_counter += 1
return cls.operation_id_counter
def __init__(self):
self.handler = None
self.logger = logging.getLogger(self.LOGGER)
self.id = self.operation_id()
# If there are no handlers, set one up explicitly because the
# terminator and propagation needs to be set. If there are,
@ -1394,6 +1404,7 @@ class ProgressIndicatorBase:
try:
formatter = logger.formatter
terminator = '\n' if logger.json else '\r'
self.json = logger.json
except AttributeError:
terminator = '\r'
else:
@ -1404,12 +1415,30 @@ class ProgressIndicatorBase:
if self.logger.level == logging.NOTSET:
self.logger.setLevel(logging.WARN)
self.logger.propagate = False
self.emit = self.logger.getEffectiveLevel() == logging.INFO
def __del__(self):
if self.handler is not None:
self.logger.removeHandler(self.handler)
self.handler.close()
def output_json(self, *, finished=False, **kwargs):
assert self.json
if not self.emit:
return
print(json.dumps(dict(
operation=self.id,
type=self.JSON_TYPE,
finished=finished,
**kwargs,
)), file=sys.stderr)
def finish(self):
if self.json:
self.output_json(finished=True)
else:
self.output('')
def justify_to_terminal_size(message):
terminal_space = get_terminal_size(fallback=(-1, -1))[0]
@ -1420,14 +1449,18 @@ def justify_to_terminal_size(message):
class ProgressIndicatorMessage(ProgressIndicatorBase):
def output(self, msg):
self.logger.info(justify_to_terminal_size(msg))
JSON_TYPE = 'progress_message'
def finish(self):
self.output('')
def output(self, msg):
if self.json:
self.output_json(message=msg)
else:
self.logger.info(justify_to_terminal_size(msg))
class ProgressIndicatorPercent(ProgressIndicatorBase):
JSON_TYPE = 'progress_percent'
def __init__(self, total=0, step=5, start=0, msg="%3.0f%%"):
"""
Percentage-based progress indicator
@ -1466,22 +1499,23 @@ class ProgressIndicatorPercent(ProgressIndicatorBase):
if pct is not None:
# truncate the last argument, if no space is available
if info is not None:
# no need to truncate if we're not outputing to a terminal
terminal_space = get_terminal_size(fallback=(-1, -1))[0]
if terminal_space != -1:
space = terminal_space - len(self.msg % tuple([pct] + info[:-1] + ['']))
info[-1] = ellipsis_truncate(info[-1], space)
if not self.json:
# no need to truncate if we're not outputing to a terminal
terminal_space = get_terminal_size(fallback=(-1, -1))[0]
if terminal_space != -1:
space = terminal_space - len(self.msg % tuple([pct] + info[:-1] + ['']))
info[-1] = ellipsis_truncate(info[-1], space)
return self.output(self.msg % tuple([pct] + info), justify=False)
return self.output(self.msg % pct)
def output(self, message, justify=True):
if justify:
message = justify_to_terminal_size(message)
self.logger.info(message)
def finish(self):
self.output('')
if self.json:
self.output_json(message=message, current=self.counter, total=self.total)
else:
if justify:
message = justify_to_terminal_size(message)
self.logger.info(message)
class ProgressIndicatorEndless: