Repository: borgbackup/borg

Issue:
add version and some system data to log / tracebacks
when we get bug reports, one often has to explicitly ask for the version, OS, arch, etc.

this could be logged into log file when borg starts and also be shown at the top or bottom of tracebacks.



Discussion:
i think this something that logbook does, which i mentionned in https://github.com/borgbackup/borg/issues/302#issuecomment-149343414...

it's the "fingers crossed" mechanism:

https://pythonhosted.org/Logbook/features.html#core-features

> There is also a special “fingers crossed” handler that, in combination with the handler stack, has the ability to accumulate all logging messages and will deliver those in case a severity level was exceeded. For example, it can withhold all logging messages for a specific request to a web application until an error record appears, in which case it will also send all withheld records to the handler it wraps. This way, you can always log lots of debugging records, but only get see them when they can actually tell you something of interest.


Resolving patch:
diff --git a/borg/archiver.py b/borg/archiver.py
--- a/borg/archiver.py
+++ b/borg/archiver.py
@@ -20,7 +20,7 @@
     format_file_mode, ExcludePattern, IncludePattern, exclude_path, adjust_patterns, to_localtime, timestamp, \
     get_cache_dir, get_keys_dir, prune_within, prune_split, unhexlify, \
     Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
-    dir_is_tagged, bigint_to_int, ChunkerParams, CompressionSpec, is_slow_msgpack, yes, \
+    dir_is_tagged, bigint_to_int, ChunkerParams, CompressionSpec, is_slow_msgpack, yes, sysinfo, \
     EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
 from .logger import create_logger, setup_logging
 logger = create_logger()
@@ -1224,16 +1224,16 @@ def main():  # pragma: no cover
     except Error as e:
         msg = e.get_message()
         if e.traceback:
-            msg += "\n%s" % traceback.format_exc()
+            msg += "\n%s\n%s" % (traceback.format_exc(), sysinfo())
         exit_code = e.exit_code
     except RemoteRepository.RPCError as e:
-        msg = 'Remote Exception.\n%s' % str(e)
+        msg = 'Remote Exception.\n%s\n%s' % (str(e), sysinfo())
         exit_code = EXIT_ERROR
     except Exception:
-        msg = 'Local Exception.\n%s' % traceback.format_exc()
+        msg = 'Local Exception.\n%s\n%s' % (traceback.format_exc(), sysinfo())
         exit_code = EXIT_ERROR
     except KeyboardInterrupt:
-        msg = 'Keyboard interrupt.\n%s' % traceback.format_exc()
+        msg = 'Keyboard interrupt.\n%s\n%s' % (traceback.format_exc(), sysinfo())
         exit_code = EXIT_ERROR
     if msg:
         logger.error(msg)
diff --git a/borg/helpers.py b/borg/helpers.py
--- a/borg/helpers.py
+++ b/borg/helpers.py
@@ -14,6 +14,7 @@ def get_terminal_size(fallback=(80, 24)):
         TerminalSize = namedtuple('TerminalSize', ['columns', 'lines'])
         return TerminalSize(int(os.environ.get('COLUMNS', fallback[0])), int(os.environ.get('LINES', fallback[1])))
 import sys
+import platform
 import time
 import unicodedata
 
@@ -887,3 +888,13 @@ def yes(msg=None, retry_msg=None, false_msg=None, true_msg=None,
         if retry_msg:
             print(retry_msg, file=ofile, end='')
             ofile.flush()
+
+
+def sysinfo():
+    info = []
+    info.append('Platform: %s' % (' '.join(platform.uname()), ))
+    if sys.platform.startswith('linux'):
+        info.append('Linux: %s %s %s  LibC: %s %s' % (platform.linux_distribution() + platform.libc_ver()))
+    info.append('Python: %s %s' % (platform.python_implementation(), platform.python_version()))
+    info.append('')
+    return '\n'.join(info)


Test patch: