From: Michael Goldish <mgoldish@redhat.com>
To: autotest@test.kernel.org, kvm@vger.kernel.org
Cc: Michael Goldish <mgoldish@redhat.com>
Subject: [KVM-AUTOTEST PATCH 3/7] [RFC] Introduce exception context strings
Date: Mon, 3 Jan 2011 20:34:07 +0200 [thread overview]
Message-ID: <1294079651-21631-3-git-send-email-mgoldish@redhat.com> (raw)
In-Reply-To: <1294079651-21631-1-git-send-email-mgoldish@redhat.com>
In complex tests (KVM) an exception string is often not informative enough and
the traceback and source code have to be examined in order to figure out what
caused the exception. Context strings are a way for tests to provide
information about what they're doing, so that when an exception is raised, this
information will be embedded in the exception string. The result is a concise
yet highly informative exception string, which should make it very easy to
figure out where/when the exception was raised.
A typical example for a test where this may be useful is KVM's reboot test.
Some exceptions can be raised either before or after the VM is rebooted (e.g.
logging into the guest can fail) and whether they are raised before or after
is critical to the understanding of the failure. Normally the traceback would
have to be examined, but the proposed method makes it easy to know where the
exception is raised without doing so. To achieve this, the reboot test should
place calls to error.context() as follows:
error.context("before reboot")
<carry out pre-reboot actions>
error.context("sending reboot command")
<send the reboot command>
error.context("after reboot")
<carry out post-reboot actions>
If login fails in the pre-reboot section, the resulting exception string can
can have something like "context: before reboot" embedded in it. (The actual
embedding is done in the next patch in the series.)
Signed-off-by: Michael Goldish <mgoldish@redhat.com>
---
client/common_lib/error.py | 82 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/client/common_lib/error.py b/client/common_lib/error.py
index f1ddaea..394f555 100644
--- a/client/common_lib/error.py
+++ b/client/common_lib/error.py
@@ -2,13 +2,13 @@
Internal global error types
"""
-import sys, traceback
+import sys, traceback, threading, logging
from traceback import format_exception
# Add names you want to be imported by 'from errors import *' to this list.
# This must be list not a tuple as we modify it to include all of our
# the Exception classes we define below at the end of this file.
-__all__ = ['format_error']
+__all__ = ['format_error', 'context', 'get_context']
def format_error():
@@ -21,6 +21,84 @@ def format_error():
return ''.join(trace)
+# Exception context information:
+# ------------------------------
+# Every function can have some context string associated with it.
+# The context string can be changed by calling context(str) and cleared by
+# calling context() with no parameters.
+# get_context() joins the current context strings of all functions in the
+# provided traceback. The result is a brief description of what the test was
+# doing in the provided traceback (which should be the traceback of a caught
+# exception).
+#
+# For example: assume a() calls b() and b() calls c().
+#
+# def a():
+# error.context("hello")
+# b()
+# error.context("world")
+# get_context() ----> 'world'
+#
+# def b():
+# error.context("foo")
+# c()
+#
+# def c():
+# error.context("bar")
+# get_context() ----> 'hello --> foo --> bar'
+
+context_data = threading.local()
+context_data.contexts = {}
+
+
+def context(c=None, log=logging.info):
+ """
+ Set the context for the currently executing function and log it as an INFO
+ message by default.
+
+ @param c: A string or None. If c is None or an empty string, the context
+ for the current function is cleared.
+ @param log: A logging function to pass the string to. If None, no function
+ will be called.
+ """
+ stack = traceback.extract_stack()
+ try:
+ key_parts = ["%s:%s:%s:" % (filename, func, lineno)
+ for filename, lineno, func, text in stack[:-2]]
+ filename, lineno, func, text = stack[-2]
+ key_parts.append("%s:%s" % (filename, func))
+ key = "".join(key_parts)
+ if c:
+ context_data.contexts[key] = c
+ if log:
+ log("Context: %s" % c)
+ elif key in context_data.contexts:
+ del context_data.contexts[key]
+ finally:
+ # Prevent circular references
+ del stack
+
+
+def get_context(tb):
+ """
+ Construct a context string from the given traceback.
+
+ @param tb: A traceback object (usually sys.exc_info()[2]).
+ """
+ l = []
+ key = ""
+ for filename, lineno, func, text in traceback.extract_tb(tb):
+ key += "%s:%s" % (filename, func)
+ # An exception's traceback is relative to the function that handles it,
+ # so instead of an exact match, we expect the traceback entries to be
+ # suffixes of the stack entries recorded using extract_stack().
+ for key_ in context_data.contexts:
+ if key_.endswith(key):
+ l.append(context_data.contexts[key_])
+ key += ":%s:" % lineno
+ return " --> ".join(l)
+
+
class JobContinue(SystemExit):
"""Allow us to bail out requesting continuance."""
pass
--
1.7.3.4
next prev parent reply other threads:[~2011-01-03 18:33 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-03 18:34 [KVM-AUTOTEST PATCH 1/7] [RFC] Fix Unhandled* exceptions Michael Goldish
2011-01-03 18:34 ` [KVM-AUTOTEST PATCH 2/7] [RFC] CmdError: remove extra blank line between methods Michael Goldish
2011-01-03 18:34 ` Michael Goldish [this message]
2011-01-03 19:26 ` [KVM-AUTOTEST PATCH 3/7] [RFC] Introduce exception context strings Eduardo Habkost
2011-01-03 19:42 ` [Autotest] " Eduardo Habkost
2011-01-03 19:48 ` Michael Goldish
2011-01-03 20:16 ` Eduardo Habkost
2011-01-03 21:07 ` Michael Goldish
2011-01-03 21:22 ` Eduardo Habkost
2011-01-03 22:06 ` [Autotest] " Eduardo Habkost
2011-01-03 22:56 ` Michael Goldish
2011-01-04 15:08 ` Eduardo Habkost
2011-01-04 15:20 ` Eduardo Habkost
2011-01-03 20:26 ` Eduardo Habkost
2011-01-03 20:41 ` [Autotest] " Michael Goldish
2011-01-03 18:34 ` [KVM-AUTOTEST PATCH 4/7] [RFC] Embed context information in exception strings Michael Goldish
2011-01-03 18:34 ` [KVM-AUTOTEST PATCH 5/7] [RFC] Set the .context attribute for exceptions in _call_test_function() Michael Goldish
2011-01-03 18:34 ` [KVM-AUTOTEST PATCH 6/7] [RFC] KVM test: use error.context() in migration_with_file_transfer Michael Goldish
2011-01-03 18:34 ` [KVM-AUTOTEST PATCH 7/7] [RFC] KVM test: use error.context() in kvm_preprocessing.py Michael Goldish
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1294079651-21631-3-git-send-email-mgoldish@redhat.com \
--to=mgoldish@redhat.com \
--cc=autotest@test.kernel.org \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox