def on_post(self, req, resp): """Handle incoming HTTP POSTs. Note: This is executed by the WSGI app, so it and anything it does is covered by the Sentry middleware. """ resp.status = falcon.HTTP_200 start_time = time.time() # NOTE(willkg): This has to return text/plain since that's what the # breakpad clients expect. resp.content_type = "text/plain" try: raw_crash, dumps = self.extract_payload(req) except MalformedCrashReport as exc: # If this is malformed, then reject it with malformed error code. msg = str(exc) mymetrics.incr("malformed", tags=["reason:%s" % msg]) resp.status = falcon.HTTP_400 resp.body = "Discarded=malformed_%s" % msg return mymetrics.incr("incoming_crash") # Add timestamps current_timestamp = utc_now() raw_crash["submitted_timestamp"] = current_timestamp.isoformat() raw_crash["timestamp"] = start_time # Add checksums and MinidumpSha256Hash raw_crash["dump_checksums"] = { dump_name: hashlib.sha256(dump).hexdigest() for dump_name, dump in dumps.items() } raw_crash["MinidumpSha256Hash"] = raw_crash["dump_checksums"].get( "upload_file_minidump", "" ) # First throttle the crash which gives us the information we need # to generate a crash id. throttle_result, rule_name, percentage = self.get_throttle_result(raw_crash) # Use a uuid if they gave us one and it's valid--otherwise create a new # one. if "uuid" in raw_crash and validate_crash_id(raw_crash["uuid"]): crash_id = raw_crash["uuid"] logger.info("%s has existing crash_id", crash_id) else: crash_id = create_crash_id( timestamp=current_timestamp, throttle_result=throttle_result ) raw_crash["uuid"] = crash_id raw_crash["type_tag"] = self.config("dump_id_prefix").strip("-") # Log the throttle result logger.info( "%s: matched by %s; returned %s", crash_id, rule_name, RESULT_TO_TEXT[throttle_result], ) mymetrics.incr("throttle_rule", tags=["rule:%s" % rule_name]) mymetrics.incr( "throttle", tags=["result:%s" % RESULT_TO_TEXT[throttle_result].lower()] ) # If the result is REJECT, then discard it if throttle_result is REJECT: resp.body = "Discarded=rule_%s" % rule_name return # If the result is a FAKEACCEPT, then we return a crash id, but throw the crash # away if throttle_result is FAKEACCEPT: resp.body = "CrashID=%s%s\n" % (self.config("dump_id_prefix"), crash_id) return # If we're accepting the cash report, then clean it up, save it and return the # CrashID to the client self.cleanup_crash_report(raw_crash) crash_report = CrashReport(raw_crash, dumps, crash_id) crash_report.set_state(STATE_SAVE) self.crashmover_queue.append(crash_report) self.hb_run_crashmover() resp.body = "CrashID=%s%s\n" % (self.config("dump_id_prefix"), crash_id)
def test_validate_crash_id(data, strict, expected): assert validate_crash_id(data, strict=strict) == expected
def on_post(self, req, resp): """Handles incoming HTTP POSTs Note: This is executed by the WSGI app, so it and anything it does is covered by the Sentry middleware. """ resp.status = falcon.HTTP_200 start_time = time.time() # NOTE(willkg): This has to return text/plain since that's what the # breakpad clients expect. resp.content_type = 'text/plain' raw_crash, dumps = self.extract_payload(req) # If we didn't get any crash data, then just drop it and move on--don't # count this as an incoming crash and don't do any more work on it if not raw_crash: resp.body = 'Discarded=1' return mymetrics.incr('incoming_crash') # Add timestamps current_timestamp = utc_now() raw_crash['submitted_timestamp'] = current_timestamp.isoformat() raw_crash['timestamp'] = start_time # Add checksums and MinidumpSha256Hash raw_crash['dump_checksums'] = { dump_name: hashlib.sha256(dump).hexdigest() for dump_name, dump in dumps.items() } raw_crash['MinidumpSha256Hash'] = raw_crash['dump_checksums'].get( 'upload_file_minidump', '') # First throttle the crash which gives us the information we need # to generate a crash id. throttle_result, rule_name, percentage = self.get_throttle_result( raw_crash) # Use a uuid if they gave us one and it's valid--otherwise create a new # one. if 'uuid' in raw_crash and validate_crash_id(raw_crash['uuid']): crash_id = raw_crash['uuid'] logger.info('%s has existing crash_id', crash_id) else: crash_id = create_crash_id(timestamp=current_timestamp, throttle_result=throttle_result) raw_crash['uuid'] = crash_id raw_crash['type_tag'] = self.config('dump_id_prefix').strip('-') # Log the throttle result logger.info('%s: matched by %s; returned %s', crash_id, rule_name, RESULT_TO_TEXT[throttle_result]) mymetrics.incr('throttle_rule', tags=['rule:%s' % rule_name]) mymetrics.incr( 'throttle', tags=['result:%s' % RESULT_TO_TEXT[throttle_result].lower()]) if throttle_result is REJECT: # If the result is REJECT, then discard it resp.body = 'Discarded=1' else: # If the result is not REJECT, then save it and return the CrashID to # the client self.crashmover_save_queue.append( CrashReport(raw_crash, dumps, crash_id)) self.hb_run_crashmover() resp.body = 'CrashID=%s%s\n' % (self.config('dump_id_prefix'), crash_id)
def on_post(self, req, resp): """Handle incoming HTTP POSTs. Note: This is executed by the WSGI app, so it and anything it does is covered by the Sentry middleware. """ resp.status = falcon.HTTP_200 start_time = time.time() # NOTE(willkg): This has to return text/plain since that's what the # breakpad clients expect. resp.content_type = 'text/plain' raw_crash, dumps = self.extract_payload(req) # If we didn't get any crash data, then just drop it and move on--don't # count this as an incoming crash and don't do any more work on it if not raw_crash: resp.body = 'Discarded=1' return mymetrics.incr('incoming_crash') # Add timestamps current_timestamp = utc_now() raw_crash['submitted_timestamp'] = current_timestamp.isoformat() raw_crash['timestamp'] = start_time # Add checksums and MinidumpSha256Hash raw_crash['dump_checksums'] = { dump_name: hashlib.sha256(dump).hexdigest() for dump_name, dump in dumps.items() } raw_crash['MinidumpSha256Hash'] = raw_crash['dump_checksums'].get('upload_file_minidump', '') # First throttle the crash which gives us the information we need # to generate a crash id. throttle_result, rule_name, percentage = self.get_throttle_result(raw_crash) # Use a uuid if they gave us one and it's valid--otherwise create a new # one. if 'uuid' in raw_crash and validate_crash_id(raw_crash['uuid']): crash_id = raw_crash['uuid'] logger.info('%s has existing crash_id', crash_id) else: crash_id = create_crash_id( timestamp=current_timestamp, throttle_result=throttle_result ) raw_crash['uuid'] = crash_id raw_crash['type_tag'] = self.config('dump_id_prefix').strip('-') # Log the throttle result logger.info('%s: matched by %s; returned %s', crash_id, rule_name, RESULT_TO_TEXT[throttle_result]) mymetrics.incr('throttle_rule', tags=['rule:%s' % rule_name]) mymetrics.incr('throttle', tags=['result:%s' % RESULT_TO_TEXT[throttle_result].lower()]) if throttle_result is REJECT: # If the result is REJECT, then discard it resp.body = 'Discarded=1' elif throttle_result is FAKEACCEPT: # If the result is a FAKEACCEPT, then we return a crash id, but throw # the crash away resp.body = 'CrashID=%s%s\n' % (self.config('dump_id_prefix'), crash_id) else: # If the result is not REJECT, then save it and return the CrashID to # the client crash_report = CrashReport(raw_crash, dumps, crash_id) crash_report.set_state(STATE_SAVE) self.crashmover_queue.append(crash_report) self.hb_run_crashmover() resp.body = 'CrashID=%s%s\n' % (self.config('dump_id_prefix'), crash_id)