def _blame_line(self, traceback): '''Figures out which line in traceback is to blame for the error. Returns a 3-tuple of (ErrorKey, StackTraceEntry, [email recipients])''' key = None blamed_entry = None email_recipients = [] for stack_line in traceback: line_type = self._get_line_type(stack_line) if line_type == api_ttypes.LineType.THIRDPARTY_WHITELIST: return None, None, None, True elif line_type in [ api_ttypes.LineType.DEFAULT, api_ttypes.LineType.KNOWN_ERROR ]: filepath = self._get_basepath(stack_line.filename) entry = api_ttypes.CodeIdentifier(filepath, stack_line.function_name, stack_line.text) blamed_entry = entry key = api_ttypes.ErrorKey(filepath, stack_line.line_number, stack_line.function_name, stack_line.text) if filepath in self.watch_all_errors: email_recipients.extend(self.watch_all_errors[filepath]) return (key, blamed_entry, email_recipients, False)
def _get_line_type(self, line): filepath = self._get_basepath(line.filename) if not filepath: return api_ttypes.LineType.BAD_FILEPATH entry = api_ttypes.CodeIdentifier(filepath, line.function_name, line.text) if entry in self.third_party_whitelist[filepath]: return api_ttypes.LineType.THIRDPARTY_WHITELIST elif not self._matches_filepath_pattern(filepath): return api_ttypes.LineType.IGNORED_FILEPATH elif entry in self.building_blocks[filepath]: return api_ttypes.LineType.BUILDING_BLOCK elif entry in self.known_errors[filepath]: return api_ttypes.LineType.KNOWN_ERROR elif self.raise_exception_pattern.match(line.text): return api_ttypes.LineType.RAISED_EXCEPTION else: return api_ttypes.LineType.DEFAULT
def setUp(self): super(BaseTestCase, self).setUp() self.popen_stub = POpenStub() self.popen_stub.stdout = StringIO( "75563df6e9d1efe44b48f6643fde9ebbd822b0c5 25 25 1\n" "author John Egan\n" "author-mail <*****@*****.**>\n" "author-time %d\n" "author-tz -0800\n" "committer John Egan\n" "committer-mail <*****@*****.**>\n" "committer-time 1356245776\n" "committer-tz -0800\n" "summary Add more robust support for string keys\n" "previous 3491c7b8e298ec81dc7583163a118e7c2250999f safe_access.py\n" "filename safe_access.py\n" " ex: a.b.[myvar] where myvar is passed in as a kwarg\n" % int(time.mktime(datetime.datetime(2017, 7, 30).timetuple()))) self._set_stub_time(datetime.datetime(2020, 1, 1)) self.smtp_stub = SMTPClientStub() self.file_open_stub = OpenFileStub() self.watchers = api_ttypes.WatchList([ api_ttypes.WatchFileEntry( email="*****@*****.**", filepath="tools/furminator.py", watch_all_errors=True, ), api_ttypes.WatchFileEntry( email="*****@*****.**", filepath="tools/furminator.py", watch_all_errors=True, ), api_ttypes.WatchFileEntry( email="*****@*****.**", filepath="lib/no/such/path/for/testing.py", watch_all_errors=True, ), ]) self.third_party_whitelist = api_ttypes.CodeIdentifierList([ api_ttypes.CodeIdentifier('facebook.py', 'post_treat_to_facebook', 'urllib.urlencode(args), post_data)'), api_ttypes.CodeIdentifier( 'SQLAlchemy-0.5.6-py2.6.egg/sqlalchemy/pool.py', 'do_get', 'raise exc.TimeoutError("QueuePool limit of size %d overflow %d ', ), ]) self.known_errors = api_ttypes.KnownErrorList([ api_ttypes.KnownError( 'lib/doghouse/authentication.py', 'check_auth', 'raise errors.BadAuthenticationError("Something smells off...")', max_alert_threshold=0, ), api_ttypes.KnownError( filename='coreservices/waterbowl/rewards/water.py', function_name='make_external_api_ttypes_request', code_fragment='raise api_ttypes.WaterbowlError(error_code=' 'api_ttypes.WaterbowlErrorCode.OUT_OF_WATER, message=str(e))', email_recipients=[ "*****@*****.**", "*****@*****.**" ], email_header= 'NOTE: This error typically does not require dev team involvement.', alert_every_n_occurrences=1, ), ]) self.building_blocks = api_ttypes.CodeIdentifierList([ api_ttypes.CodeIdentifier( 'apps/shopkick/doghouse/lib/base.py', '_get_request_param', 'raise errors.BadRequestError("Missing param %s" % name)'), ]) self.ignored_exceptions = api_ttypes.IgnoredExceptionList( ['exceptions.BananaException']) self.disowned_files = api_ttypes.FileDisownershipList([ api_ttypes.FileDisownershipEntry( email='*****@*****.**', filepath='scripts', designated_email='*****@*****.**') ]) self.config_storage_stub = StubStorage(partition=None) self.config_storage_stub["watch_list"] = self.watchers self.config_storage_stub[ "third_party_whitelist"] = self.third_party_whitelist self.config_storage_stub["known_errors"] = self.known_errors self.config_storage_stub["building_blocks"] = self.building_blocks self.config_storage_stub[ "ignored_exceptions"] = self.ignored_exceptions self.config_storage_stub["disownership_list"] = self.disowned_files self.errors_storage_stub = StubStorage(partition=None) self.saved_config = copy.deepcopy(flawless.lib.config.get().__dict__) self.test_config = flawless.lib.config.get() self.test_config.__dict__ = dict( (o.name, o.default) for o in flawless.lib.config.OPTIONS) self.test_config.repo_dir = "/tmp" self.test_config.report_only_after_minimum_date = "2010-01-01" self.test_config.report_error_threshold = 1 self.test_config.only_blame_filepaths_matching = [ r"^coreservices(?!.*/thrift/).*$", r"lib/.*", r"tools/.*", r"scripts/.*" ] self.test_config.report_runtime_package_directory_names = [ "site-packages" ] self.test_config.config_dir_path = "../config" self.handler = FlawlessThriftServiceHandler( open_process_func=self.popen_stub, storage_factory=lambda partition: self.errors_storage_stub if partition else self.config_storage_stub, smtp_client_cls=self.smtp_stub, time_func=lambda: self.stub_time, thread_cls=ThreadStub, )