Переглянути джерело

pass msgid for common errors

Marian Beermann 8 роки тому
батько
коміт
fcad0ddab4
3 змінених файлів з 62 додано та 4 видалено
  1. 39 2
      docs/internals/frontends.rst
  2. 7 2
      src/borg/archiver.py
  3. 16 0
      src/borg/logger.py

+ 39 - 2
docs/internals/frontends.rst

@@ -45,7 +45,7 @@ progress_message
 
     operation
         unique, opaque integer ID of the operation
-    msgid
+    :ref:`msgid <msgid>`
         Message ID of the operation (may be *none*)
     finished
         boolean indicating whether the operation has finished, only the last object for an *operation*
@@ -58,7 +58,7 @@ progress_percent
 
     operation
         unique, opaque integer ID of the operation
-    msgid
+    :ref:`msgid <msgid>`
         Message ID of the operation (may be *none*)
     finished
         boolean indicating whether the operation has finished, only the last object for an *operation*
@@ -90,6 +90,8 @@ log_message
         Name of the emitting entity
     message
         Formatted log message
+    :ref:`msgid <msgid>`
+        Message ID, may be *none* or absent
 
 Standard output
 ---------------
@@ -188,3 +190,38 @@ comment
 Listing the contents of an archive can produce *a lot* of JSON. Each item (file, directory, ...) is described
 by one object in the *files* array of the :ref:`borg_list` output. Refer to the *borg list* documentation for
 the available keys and their meaning.
+
+.. _msgid:
+
+Message IDs
+-----------
+
+Message IDs are strings that essentially give a log message or operation a name, without actually using the
+full text, since texts change more frequently. Message IDs are unambiguous and reduce the need to parse
+log messages.
+
+Assigned message IDs are:
+
+.. note::
+
+    This list is incomplete.
+
+Errors
+    - Archive.AlreadyExists
+    - Archive.DoesNotExist
+    - Archive.IncompatibleFilesystemEncodingError
+    - IntegrityError
+    - NoManifestError
+    - PlaceholderError
+
+Operations
+    - cache.begin_transaction
+    - cache.commit
+    - cache.sync
+    - repository.compact_segments
+    - repository.replay_segments
+    - repository.check_segments
+    - check.verify_data
+    - extract
+    - extract.permissions
+    - archive.delete

+ 7 - 2
src/borg/archiver.py

@@ -3287,7 +3287,7 @@ def main():  # pragma: no cover
          signal_handler('SIGUSR2', sig_trace_handler), \
          signal_handler('SIGINFO', sig_info_handler):
         archiver = Archiver()
-        msg = tb = None
+        msg = msgid = tb = None
         tb_log_level = logging.ERROR
         try:
             args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND'))
@@ -3304,11 +3304,13 @@ def main():  # pragma: no cover
             exit_code = archiver.run(args)
         except Error as e:
             msg = e.get_message()
+            msgid = type(e).__qualname__
             tb_log_level = logging.ERROR if e.traceback else logging.DEBUG
             tb = "%s\n%s" % (traceback.format_exc(), sysinfo())
             exit_code = e.exit_code
         except RemoteRepository.RPCError as e:
             important = e.exception_class not in ('LockTimeout', )
+            msgid = e.exception_class
             tb_log_level = logging.ERROR if important else logging.DEBUG
             if important:
                 msg = e.exception_full
@@ -3319,6 +3321,7 @@ def main():  # pragma: no cover
             exit_code = EXIT_ERROR
         except Exception:
             msg = 'Local Exception'
+            msgid = 'Exception'
             tb_log_level = logging.ERROR
             tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
             exit_code = EXIT_ERROR
@@ -3329,14 +3332,16 @@ def main():  # pragma: no cover
             exit_code = EXIT_ERROR
         except SigTerm:
             msg = 'Received SIGTERM'
+            msgid = 'Signal.SIGTERM'
             tb_log_level = logging.DEBUG
             tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
             exit_code = EXIT_ERROR
         except SigHup:
             msg = 'Received SIGHUP.'
+            msgid = 'Signal.SIGHUP'
             exit_code = EXIT_ERROR
         if msg:
-            logger.error(msg)
+            logger.error(msg, msgid=msgid)
         if tb:
             logger.log(tb_log_level, tb)
         if args.show_rc:

+ 16 - 0
src/borg/logger.py

@@ -165,24 +165,38 @@ def create_logger(name=None):
             return self.__logger.setLevel(*args, **kw)
 
         def log(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.log(*args, **kw)
 
         def exception(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.exception(*args, **kw)
 
         def debug(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.debug(*args, **kw)
 
         def info(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.info(*args, **kw)
 
         def warning(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.warning(*args, **kw)
 
         def error(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.error(*args, **kw)
 
         def critical(self, *args, **kw):
+            if 'msgid' in kw:
+                kw.setdefault('extra', {})['msgid'] = kw.pop('msgid')
             return self.__logger.critical(*args, **kw)
 
     return LazyLogger(name)
@@ -194,6 +208,8 @@ class JsonFormatter(logging.Formatter):
         'levelname',
         'name',
         'message',
+        # msgid is an attribute we made up in Borg to expose a non-changing handle for log messages
+        'msgid',
     )
 
     # Other attributes that are not very useful but do exist: