summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authortonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-12 22:06:48 +0000
committertonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-12 22:06:48 +0000
commit5bda847a21a067c2ae877dec63d061f4513fa70e (patch)
treef5b1a0cf6ea36a628092383fd1873eaacb85e95a /tools
parente18e10788549528b0a334989e711c947f1212ff2 (diff)
downloadchromium_src-5bda847a21a067c2ae877dec63d061f4513fa70e.zip
chromium_src-5bda847a21a067c2ae877dec63d061f4513fa70e.tar.gz
chromium_src-5bda847a21a067c2ae877dec63d061f4513fa70e.tar.bz2
[Telemetry] Make unhandled exception output more useful.
This should help tremendously in diagnosing flake on the bots. Default format: --------------------------- Traceback (most recent call last): File "tools/perf/run_benchmark", line 23, in <module> sys.exit(test_runner.Main()) File "tools/perf/../telemetry/telemetry/test_runner.py", line 290, in Main return command.Run(options, args) File "tools/perf/../telemetry/telemetry/test_runner.py", line 198, in Run return min(255, self._test().Run(copy.copy(options))) File "tools/perf/../telemetry/telemetry/test.py", line 53, in Run results = page_runner.Run(test, ps, expectations, options) File "tools/perf/../telemetry/telemetry/page/page_runner.py", line 330, in Run possible_browser, results, state) File "tools/perf/../telemetry/telemetry/page/page_runner.py", line 213, in _PrepareAndRunPage credentials_path, page.archive_path) File "tools/perf/../telemetry/telemetry/page/page_runner.py", line 54, in StartBrowser test.DidStartBrowser(self.browser) File "/work/chromium/src/tools/perf/measurements/page_cycler.py", line 71, in DidStartBrowser self._memory_metric = memory.MemoryMetric(browser) File "/work/chromium/src/tools/perf/metrics/memory.py", line 32, in __init__ self._start_commit_charge = self._browser.memory_stats['SystemCommitCharge'] File "tools/perf/../telemetry/telemetry/core/browser.py", line 166, in memory_stats result = self._GetStatsCommon(self._platform_backend.GetMemoryStats) File "tools/perf/../telemetry/telemetry/core/browser.py", line 99, in _GetStatsCommon for child_pid in self._platform_backend.GetChildPids(browser_pid): File "tools/perf/../telemetry/telemetry/core/platform/posix_platform_backend.py", line 44, in GetChildPids return proc_util.GetChildPids(processes, pid) File "tools/perf/../telemetry/telemetry/core/platform/proc_util.py", line 86, in GetChildPids for foo, curr_pid, curr_ppid, state in processes: ValueError: need more than 3 values to unpack --------------------------- New format: --------------------------- Traceback (most recent call last): <module> at tools/perf/run_benchmark:23 sys.exit(test_runner.Main()) Main at tools/telemetry/telemetry/test_runner.py:303 return command.Run(options, args) Run at tools/telemetry/telemetry/test_runner.py:211 return min(255, self._test().Run(copy.copy(options))) Run at tools/telemetry/telemetry/test.py:53 results = page_runner.Run(test, ps, expectations, options) Run at tools/telemetry/telemetry/page/page_runner.py:330 possible_browser, results, state) _PrepareAndRunPage at tools/telemetry/telemetry/page/page_runner.py:213 credentials_path, page.archive_path) StartBrowser at tools/telemetry/telemetry/page/page_runner.py:54 test.DidStartBrowser(self.browser) DidStartBrowser at tools/perf/measurements/page_cycler.py:71 self._memory_metric = memory.MemoryMetric(browser) __init__ at tools/perf/metrics/memory.py:32 self._start_commit_charge = self._browser.memory_stats['SystemCommitCharge'] memory_stats at tools/telemetry/telemetry/core/browser.py:166 result = self._GetStatsCommon(self._platform_backend.GetMemoryStats) _GetStatsCommon at tools/telemetry/telemetry/core/browser.py:99 for child_pid in self._platform_backend.GetChildPids(browser_pid): GetChildPids at tools/telemetry/telemetry/core/platform/posix_platform_backend.py:44 return proc_util.GetChildPids(processes, pid) GetChildPids at tools/telemetry/telemetry/core/platform/proc_util.py:86 for foo, curr_pid, curr_ppid, state in processes: Locals: child_dict : defaultdict(<type 'list'>, {}) pid : 5510 processes : [['1', '0', 'Ss'], ['15', '1', 'Ss'], ['16', '1', 'Ss'], ['17 ... 99', 'R+'], ['78347', '78344', 'Ss'], ['78349', '78347', 'S']] (truncated) ValueError: need more than 3 values to unpack --------------------------- BUG= Review URL: https://codereview.chromium.org/64553004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234648 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/telemetry/telemetry/test_runner.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/telemetry/telemetry/test_runner.py b/tools/telemetry/telemetry/test_runner.py
index adb95a8..ec62132 100644
--- a/tools/telemetry/telemetry/test_runner.py
+++ b/tools/telemetry/telemetry/test_runner.py
@@ -10,9 +10,11 @@ actually running the test is in Test and PageRunner."""
import copy
import inspect
import json
+import math
import optparse
import os
import sys
+import traceback
from telemetry import test
from telemetry.core import browser_options
@@ -20,6 +22,71 @@ from telemetry.core import discover
from telemetry.core import util
+def PrintFormattedException(exception_class, exception, tb):
+ """Prints an Exception in a more useful format than the default.
+
+ TODO(tonyg): Consider further enhancements. For instance:
+ - Report stacks to maintainers like depot_tools does.
+ - Add a debug flag to automatically start pdb upon exception.
+ """
+ def _GetFinalFrame(frame):
+ final_frame = None
+ while frame is not None:
+ final_frame = frame
+ frame = frame.tb_next
+ return final_frame
+
+ def _AbbreviateMiddle(target, middle, length):
+ assert length >= 0, 'Must provide positive length'
+ assert len(middle) <= length, 'middle must not be greater than length'
+ if len(target) <= length:
+ return target
+ half_length = (length - len(middle)) / 2.
+ return '%s%s%s' % (target[:int(math.floor(half_length))],
+ middle,
+ target[-int(math.ceil(half_length)):])
+
+ base_dir = os.path.abspath(util.GetChromiumSrcDir())
+ formatted_exception = traceback.format_exception(
+ exception_class, exception, tb)
+ extracted_tb = traceback.extract_tb(tb)
+ traceback_header = formatted_exception[0].strip()
+ exception = formatted_exception[-1].strip()
+ local_variables = _GetFinalFrame(tb).tb_frame.f_locals
+
+ # Format the traceback.
+ print >> sys.stderr
+ print >> sys.stderr, traceback_header
+ for filename, line, function, text in extracted_tb:
+ filename = os.path.abspath(filename).lstrip(base_dir)
+ print >> sys.stderr, ' %s at %s:%d' % (function, filename, line)
+ print >> sys.stderr, ' %s' % text
+
+ # Format the locals.
+ if local_variables:
+ print >> sys.stderr
+ print >> sys.stderr, 'Locals:'
+ longest_variable = max([len(v) for v in local_variables.keys()])
+ for variable, value in sorted(local_variables.iteritems()):
+ if variable == 'self':
+ continue
+ value = repr(value)
+ possibly_truncated_value = _AbbreviateMiddle(value, ' ... ', 128)
+ truncation_indication = ''
+ if len(possibly_truncated_value) != len(value):
+ truncation_indication = ' (truncated)'
+ print >> sys.stderr, ' %s: %s%s' % (variable.ljust(longest_variable + 1),
+ possibly_truncated_value,
+ truncation_indication)
+
+ # Format the exception.
+ print >> sys.stderr
+ print >> sys.stderr, exception
+
+
+sys.excepthook = PrintFormattedException
+
+
class Command(object):
usage = ''