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

Unified Diff: appengine/findit/crash/crash_report.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_pipeline.py ('k') | appengine/findit/crash/crash_report_with_dependencies.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: appengine/findit/crash/crash_report.py
diff --git a/appengine/findit/crash/crash_report.py b/appengine/findit/crash/crash_report.py
index fcae4a253189bd187f2593b523e6b4b2a7541234..2fd96d23cc27314bac2f27982da6cf5302f8722d 100644
--- a/appengine/findit/crash/crash_report.py
+++ b/appengine/findit/crash/crash_report.py
@@ -2,16 +2,35 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import logging
+from collections import defaultdict
from collections import namedtuple
+import logging
+
+
+class _FrozenDict(dict):
+ """An immutable ``dict`` (or some approximation thereof).
-from crash.stacktrace import Stacktrace
+ 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 CrashReport(namedtuple('CrashReport',
- ['crashed_version', 'signature', 'platform', 'stacktrace',
- 'regression_range'])):
- """A reported crash we want to analyze.
+class CrashReport(namedtuple(
+ 'CrashReport', ['crashed_version', 'signature', 'platform', 'stacktrace',
+ 'regression_range', 'dependencies', 'dependency_rolls'])):
+ """A crash report with all information needed for analysis for clients.
This class comprises the inputs to the Predator library; as distinguished
from the Culprit class, which comprises the outputs/results of Predator's
@@ -19,41 +38,32 @@ class CrashReport(namedtuple('CrashReport',
a single CrashAnalysis(ndb.Model) class, but that's up to them; in
the library we keep inputs and outputs entirely distinct.
- Args:
+ 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 name; e.g., 'win', 'mac', 'linux', 'android',
- 'ios', etc.
+ 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.
- regression_range (pair or None): a pair of the last-good and first-bad
- versions. N.B., because this is an input, it is up to clients
- to call ``DetectRegressionRange`` (or whatever else) in order to
- provide this information. In addition, while this class does
- support storing ``None`` to indicate a missing regression range
- (because the ClusterFuzz client wants that feature), the
- CL-classifier doesn't actually support that so you won't get a
- very good Culprit. The Component- and project-classifiers do still
- return some results at least.
+ regression_range (pair of str or None): a pair of ``last_good_version`` and
+ ``first_bad_version``. The regression_range can be ``None``.
+ 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, crashed_version, signature, platform, stacktrace,
- regression_range):
- assert isinstance(stacktrace, Stacktrace), TypeError(
- 'In the fourth argument to CrashReport constructor, '
- 'expected Stacktrace object, but got %s object instead.'
- % stacktrace.__class__.__name__)
-
- if regression_range is None: # pragma: no cover
- logging.warning('CrashReport.__init__: '
- 'Got ``None`` for the regression range.')
- else:
- # We must ensure that the regression range is immutable, both
- # for semantic reasons and so that it is hashable as is required
- # for memoization.
- regression_range = tuple(regression_range)
-
- return super(cls, CrashReport).__new__(
- cls, crashed_version, signature, platform, stacktrace, regression_range)
+ regression_range, dependencies, dependency_rolls):
+ return super(CrashReport, cls).__new__(
+ cls, crashed_version, signature, platform, stacktrace,
+ tuple(regression_range) if regression_range else None,
+ _FrozenDict(dependencies) if dependencies else {},
+ _FrozenDict(dependency_rolls) if dependency_rolls else {})
« no previous file with comments | « appengine/findit/crash/crash_pipeline.py ('k') | appengine/findit/crash/crash_report_with_dependencies.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698