Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2490)

Unified Diff: appengine/findit/crash/crash_report_with_dependencies.py

Issue 2663063007: [Predator] Switch from anonymous dict to CrashData. (Closed)
Patch Set: Rebase and fix delta test. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « appengine/findit/crash/crash_report.py ('k') | appengine/findit/crash/findit.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: appengine/findit/crash/crash_report_with_dependencies.py
diff --git a/appengine/findit/crash/crash_report_with_dependencies.py b/appengine/findit/crash/crash_report_with_dependencies.py
deleted file mode 100644
index c673f30a9296bfd6108cf92be8c302c1b54bbf0c..0000000000000000000000000000000000000000
--- a/appengine/findit/crash/crash_report_with_dependencies.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from collections import defaultdict
-from collections import namedtuple
-import logging
-
-
-class _FrozenDict(dict):
- """An immutable ``dict`` (or some approximation thereof).
-
- The goal of this class is to render a ``dict`` hashable, so
- that it can be used as a key in other ``dict``s, so that in
- turn we can use our ``MemoizedFunction`` on functions taking
- ``CrashReportWithDependencies`` as an argument.
-
- For now, we simply define the ``__hash__`` method and assume clients
- will not try to mutate instances after they have been stored as keys
- in another ``dict``. In the future it may be worth taking further
- steps to make it more difficult for clients to do such mutation.
-
- N.B., the ``__init__`` method will clone the ``dict`` argument. There
- doesn't seem to be an easy way around this.
- """
- def __hash__(self):
- return hash(tuple(sorted(self.items())))
-
-
-class CrashReportWithDependencies(
- namedtuple('CrashReportWithDependencies', [
- 'crashed_version', 'signature', 'platform', 'stacktrace',
- 'last_good_version', 'first_bad_version', 'dependencies',
- 'dependency_rolls'])):
- """A crash report annotated with extra information for the CL classifier.
-
- This class extends ``CrashReport`` with some additional information
- about deps. In particular, this is useful for the CL-classifier since
- this information is feature-independent and suspect-independent,
- so we can compute it just once and store the results. In addition,
- this class happens to be the "X" for the loglinear model underlying
- ``LogLinearChangelistClassifier``.
-
- Properties:
- crashed_version (str): The version of Chrome in which the crash occurred.
- signature (str): The signature of the crash on the Chrome crash server.
- platform (str): The platform affected by the crash; e.g., 'win',
- 'mac', 'linux', 'android', 'ios', etc.
- stacktrace (Stacktrace): The stacktrace of the crash. N.B., this is
- an object generated by parsing the string containing the stack trace;
- we do not store the string itself.
- last_good_version (str): the last known-good revision for this crash.
- first_bad_version (str): the first known-bad revision for this crash.
- regression_range (pair of str): a pair of ``last_good_version`` and
- ``first_bad_version``. Offered for convenience, to match the API of
- ``CrashReport``. Note that, unlike ``CrashReport``, we do not permit
- ``None`` as a regression range.
- dependencies (_FrozenDict): An immutable dict from dependency paths to
- ``Dependency`` objects. The keys are all those deps which are
- used by both the ``crashed_version`` of the code, and at least
- one frame in the ``stacktrace.crash_stack``.
- dependency_rolls (_FrozenDict) An immutable dict from dependency
- paths to ``DependencyRoll`` objects. The keys are all those
- dependencies which (1) occur in the regression range for the
- ``platform`` where the crash occurred, (2) neither add nor delete
- a dependency, and (3) are also keys of ``dependencies``.
- """
- __slots__ = ()
-
- def __new__(cls, report, dependency_fetcher):
- """Annotate a crash report with dependencies.
-
- N.B., because the CL-classifier does not currenly support missing
- regression ranges, if the regression range of the ``report`` is
- ``None`` then this constructor will return ``None`` rather than
- constructing the new annotated crash report. If one (or both) of the
- components of the regression range are ``None``, we will log a warning
- but nevertheless construct the annotated crash report to the extent
- we can. This is to maintain compatibility with the current unittests,
- but really we should return ``None`` since the CL-classifiers do not
- support open or half-open regression ranges either. In the future
- it would probably be better to raise a ``ValueError`` rather than
- returning ``None``
-
- Args:
- report (CrashReport): The original crash report given to Predator,
- which we extend.
- dependency_fetcher (ChromeDependencyFetcher): For getting dep information.
- """
- if not report.regression_range:
- logging.warning('%s.__new__: Missing regression range for report: %s',
- cls.__name__, str(report))
- # Give up.
- return None
-
- last_good_version = report.regression_range[0]
- if not last_good_version:
- logging.warning('%s.__new__: Missing last-good version for report: %s',
- cls.__name__, str(report))
- # Proceed as if everything was normal.
-
- first_bad_version = report.regression_range[1]
- if not first_bad_version:
- logging.warning('%s.__new__: Missing first-bad version for report: %s',
- cls.__name__, str(report))
- # Proceed as if everything was normal.
-
- logging.info('%s.__new__: Regression range %s:%s',
- cls.__name__, last_good_version, first_bad_version)
-
- # Short-circuit when we know the deps must be empty.
- if not report.stacktrace.crash_stack:
- logging.warning('%s.__new__: Missing or empty crash stack for report: %s',
- cls.__name__, str(report))
- dependencies = _FrozenDict()
- else:
- # Get all the dependencies used by the version that crashed.
- crashed_version_deps = dependency_fetcher.GetDependency(
- report.crashed_version, report.platform)
- # Filter them to only retain those which are used by some frame in
- # the callstack causing the crash (and which are truthy).
- dependencies = _FrozenDict({
- dep_path: crashed_version_deps[dep_path]
- for dep_path in (
- # N.B., returning duplicate dep paths works just fine.
- frame.dep_path
- for frame in report.stacktrace.crash_stack)
- if dep_path and dep_path in crashed_version_deps
- })
-
- # Short-circuit when we know the deprolls must be empty.
- if not dependencies:
- logging.warning('%s.__new__: Empty deps and dep rolls for report: %s',
- cls.__name__, str(report))
- dependency_rolls = _FrozenDict()
- else:
- # Get ``DependencyRoll` objects for all dependencies in the regression
- # range (for the particular platform that crashed).
- regression_range_dep_rolls = dependency_fetcher.GetDependencyRollsDict(
- last_good_version, first_bad_version, report.platform)
- # Filter out the ones which add or delete a dependency, because we
- # can't really be sure whether to blame them or not. This rarely
- # happens, so our inability to decide shouldn't be too much of a problem.
- def HasBothRevisions(dep_path, dep_roll):
- has_both_revisions = bool(dep_roll.old_revision) and bool(
- dep_roll.new_revision)
- if not has_both_revisions:
- logging.info(
- 'Skip %s dependency %s',
- 'added' if dep_roll.new_revision else 'deleted',
- dep_path)
- return has_both_revisions
- # Apply the above filter, and also filter to only retain those
- # which occur in ``crashed_stack_deps``.
- dependency_rolls = _FrozenDict({
- dep_path: dep_roll
- for dep_path, dep_roll in regression_range_dep_rolls.iteritems()
- if HasBothRevisions(dep_path, dep_roll) and dep_path in dependencies
- })
-
- return super(cls, CrashReportWithDependencies).__new__(
- cls,
- crashed_version = report.crashed_version,
- signature = report.signature,
- platform = report.platform,
- stacktrace = report.stacktrace,
- last_good_version = last_good_version,
- first_bad_version = first_bad_version,
- dependencies = dependencies,
- dependency_rolls = dependency_rolls,
- )
-
- @property
- def regression_range(self):
- """Returns a pair of the last-good and first-bad revisions.
-
- Note that even if both revisions are ``None``, this property still
- returns a pair. It never returns ``None``.
- """
- return self.last_good_version, self.first_bad_version
« no previous file with comments | « appengine/findit/crash/crash_report.py ('k') | appengine/findit/crash/findit.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698