def test_scope_event_processor_order(sentry_init, capture_events): def before_send(event, hint): event["message"] += "baz" return event sentry_init(debug=True, before_send=before_send) events = capture_events() with push_scope() as scope: @scope.add_event_processor def foo(event, hint): event["message"] += "foo" return event with push_scope() as scope: @scope.add_event_processor def bar(event, hint): event["message"] += "bar" return event capture_message("hi") event, = events assert event["message"] == "hifoobarbaz"
def wrapped(self, *args, **kwargs): start_time = kwargs.pop("start_time", None) if start_time and not self.request.retries: total_time = int((time() - start_time) * 1000) statsd.timing(self.name + ".timing", total_time) statsd.incr(self.name + ".total") statsd.incr("news.tasks.all_total") if settings.MAINTENANCE_MODE and self.name not in MAINTENANCE_EXEMPT: if not settings.READ_ONLY_MODE: # record task for later QueuedTask.objects.create( name=self.name, args=args, kwargs=kwargs, ) statsd.incr(self.name + ".queued") else: statsd.incr(self.name + ".not_queued") return try: return func(*args, **kwargs) except ( IOError, NewsletterException, requests.RequestException, RetryTask, sfapi.SalesforceExpiredSession, sfapi.SalesforceGeneralError, sfapi.SalesforceRefusedRequest, sfapi.SalesforceResourceNotFound, sfapi.SalesforceAuthenticationFailed, sfapi.SalesforceMalformedRequest, SilverpopResponseException, ) as e: # These could all be connection issues, so try again later. # IOError covers URLError and SSLError. if ignore_error(e): with sentry_sdk.push_scope() as scope: scope.set_tag("action", "ignored") sentry_sdk.capture_exception() return try: if not (isinstance(e, RetryTask) or ignore_error_post_retry(e)): with sentry_sdk.push_scope() as scope: scope.set_tag("action", "retried") sentry_sdk.capture_exception() # ~68 hr at 11 retries statsd.incr(f"{self.name}.retries.{self.request.retries}") statsd.incr(f"news.tasks.retries.{self.request.retries}") raise self.retry(countdown=exponential_backoff(self.request.retries)) except self.MaxRetriesExceededError: statsd.incr(self.name + ".retry_max") statsd.incr("news.tasks.retry_max_total") # don't bubble certain errors if ignore_error_post_retry(e): return sentry_sdk.capture_exception()
def test_scope_leaks_cleaned_up(sentry_init, caplog): caplog.set_level(logging.WARNING) sentry_init(debug=True) old_stack = list(Hub.current._stack) with push_scope(): push_scope() assert Hub.current._stack == old_stack (record,) = (x for x in caplog.records if x.levelname == "WARNING") assert record.message.startswith("Leaked 1 scopes:")
def run_collection(self, collection, run_until_timestamp, args): # Early return? if run_until_timestamp and run_until_timestamp < datetime.datetime.utcnow( ).timestamp(): return if collection.transform_type: logger = logging.getLogger( 'ocdskingfisher.cli.transform-collections') logger.info("Starting to transform collection " + str(collection.database_id)) if not args.quiet: print("Collection " + str(collection.database_id)) transform = get_transform_instance( collection.transform_type, self.config, self.database, collection, run_until_timestamp=run_until_timestamp, ) try: transform.process() except Exception as e: traceback.print_tb(e.__traceback__) with sentry_sdk.push_scope() as scope: scope.set_tag("transform_collection", collection.database_id) sentry_sdk.capture_exception(e)
def sentry_exc(error, userscope, exclevel, extra): with push_scope() as scope: scope.user = userscope scope.level = exclevel for key in extra: scope.set_tag(key, extra[key]) sentry_sdk.capture_exception(error)
def load_data_from_request(request): data = None if request.method == "POST": if request.content_type in ["", "text/plain", "application/json"]: data = request.body else: data = request.POST.get("data") else: data = request.GET.get("data") if not data: return None # add the data in sentry's scope in case there's an exception with push_scope() as scope: scope.set_context("data", data) compression = (request.GET.get("compression") or request.POST.get("compression") or request.headers.get("content-encoding", "")) compression = compression.lower() if compression == "gzip" or compression == "gzip-js": try: data = gzip.decompress(data) except (EOFError, OSError) as error: raise RequestParsingError("Failed to decompress data. %s" % (str(error))) if compression == "lz64": if not isinstance(data, str): data = data.decode() data = data.replace(" ", "+") data = lzstring.LZString().decompressFromBase64(data) if not data: raise RequestParsingError("Failed to decompress data.") data = data.encode("utf-16", "surrogatepass").decode("utf-16") base64_decoded = None try: base64_decoded = base64_decode(data) except Exception: pass if base64_decoded: data = base64_decoded try: # parse_constant gets called in case of NaN, Infinity etc # default behaviour is to put those into the DB directly # but we just want it to return None data = json.loads(data, parse_constant=lambda x: None) except (json.JSONDecodeError, UnicodeDecodeError) as error_main: raise RequestParsingError("Invalid JSON: %s" % (str(error_main))) # TODO: data can also be an array, function assumes it's either None or a dictionary. return data
def __init__(self, request, title: str, status: int = HTTPStatus.INTERNAL_SERVER_ERROR, previous: Optional[BaseException] = None, to_sentry: Optional[bool] = False, additional_data: Optional[dict] = None, detail_type: Optional[str] = None, detail: Optional[str] = None, extra_headers: Optional[Tuple[Tuple]] = ()): super().__init__(title) self._request = request self._status_code = status self._title = title self._type = detail_type self._detail = detail self._previous = previous self._extra_headers = extra_headers if additional_data: self._additional_data = additional_data else: self._additional_data = {} if to_sentry: with sentry_sdk.push_scope() as scope: for key, value in self.__dict__.items(): scope.set_extra(key, value) sentry_sdk.capture_exception(self)
def inner(*args, **kwargs): event_id = sentry_sdk.capture_event(*args, **kwargs) Hub.current.client.flush() with push_scope(): return wait_for_ingest_consumer(lambda: eventstore.get_event_by_id( settings.SENTRY_PROJECT, event_id))
def log(self, out, err, returncode): if returncode == 0: return tags = self.opts.tags or {} tags.update({ 'returncode': returncode, 'callable': self.args[0] }) extra = self.opts.extra or {} extra.update({ 'returncode': returncode, 'command': self.get_command(), }) extra.update(string_to_chunks('stdout', out.rstrip())) extra.update(string_to_chunks('stderr', err.rstrip())) capture_message_kwargs = dict( message=self.get_raven_message(returncode), level=logging.ERROR, tags=tags, extra=extra, ) if self.opts.debug: pprint(capture_message_kwargs) else: with sentry_sdk.push_scope() as scope: for k, v in iteritems(extra): scope.set_extra(k, v) for k, v in iteritems(tags): scope.set_tag(k, v) sentry_sdk.capture_message(capture_message_kwargs["message"], level=capture_message_kwargs["level"])
def test_stuff(url, warn=10, crit=20): try: r = requests.get(url, timeout=1) except Exception as e: # We capture exception in order to send an UNKNOWN to nagios. # but we send information to sentry, with warning level instead of critical with push_scope() as scope: scope.set_tag("tested-url", url) scope.level = 'warning' capture_exception(e) return("UNKNOWN",str(e)) r = requests.get(url, timeout=1) if r.status_code >= 400: return("CRITICAL", f"code {r.status_code}") elapsed = r.elapsed.total_seconds() if r.elapsed.total_seconds() > crit: return("CRITICAL", "Elapsed time = {}".format(elapsed)) if r.elapsed.total_seconds() > warn: return("WARNING", "Elapsed time = {}".format(elapsed)) # test stuff return("OK", f"elapsed: {elapsed} {r.status_code}")
def handle_event(event: Event, context: Context) -> None: """Calls the handler for the given event. Exceptions are caught and generate both error logs and sentry issues. Events are not retried after an exception. """ log.debug( "Processing event", event_=event, latest_confirmed_block=context.latest_confirmed_block, latest_unconfirmed_block=context.get_latest_unconfirmed_block(), ) handler = HANDLERS.get(type(event)) if handler: with sentry_sdk.push_scope() as sentry_scope: sentry_scope.set_tag("event", event.__class__.__name__) try: with metrics.collect_event_metrics(event): handler(event, context) log.debug( "Processed event", num_scheduled_events=context.database. scheduled_event_count(), ) except Exception as ex: # pylint: disable=broad-except log.error("Error during event handler", handled_event=event, exc_info=ex) sentry_sdk.capture_exception(ex)
def _load_data(request) -> Optional[Union[Dict, List]]: if request.method == "POST": if request.content_type == "application/json": data = request.body if request.headers.get("content-encoding", "").lower() == "gzip": data = gzip.decompress(data) else: data = request.POST.get("data") else: data = request.GET.get("data") if not data: return None # add the data in sentry's scope in case there's an exception with push_scope() as scope: scope.set_context("data", data) # Is it plain json? try: data = json.loads(data) except json.JSONDecodeError: # if not, it's probably base64 encoded from other libraries data = json.loads( base64.b64decode(data.replace(" ", "+") + "===").decode( "utf8", "surrogatepass").encode("utf-16", "surrogatepass")) # FIXME: data can also be an array, function assumes it's either None or a dictionary. return data
def respond(): st_time = time.time() last_utterances = request.json["sentences"] utterances_histories = request.json["utterances_histories"] response = [] for last_utterance, utterances_history in zip(last_utterances, utterances_histories): response = response + check( last_utterance, vectorizer=vectorizer, vectorized_phrases=vectorized_phrases, phrase_list=phrase_list, confidence_threshold=CONFIDENCE_THRESHOLD, utterances_history=utterances_history, ) if not response: with sentry_sdk.push_scope() as scope: scope.set_extra("last_utterances", last_utterances) sentry_sdk.capture_message( f"No response in topicalchat_{TOPIC_NAME}_tfidf_retrieva") response = [["sorry", 0]] assert len(response[0]) == 2 total_time = time.time() - st_time logger.info( f"topicalchat_{TOPIC_NAME}_tfidf_retrieval exec time: {total_time:.3f}s" ) logger.info(response) return jsonify(response)
async def on_application_command_error(ctx, error): logging.info(error) if isinstance(error, commands.CheckFailure): await ctx.respond("You are not authorized to use this command here.", ephemeral=True) elif isinstance(error, commands.errors.MissingPermissions): await ctx.respond("You are not authorized to use this command here.", ephemeral=True) elif isinstance(error, commands.UserInputError): await ctx.respond(error) else: error_to_display = error.original if hasattr(error, 'original') else error errorstr = repr(error_to_display) if len(errorstr) < 1990: await ctx.respond(f"```{errorstr}```") else: await ctx.respond( content= "An error occured, please see attachment for the full message.", file=discord.File(io.StringIO(error_to_display), filename="error.txt")) with push_scope() as scope: scope.set_tag("guild", ctx.guild.id if ctx.guild else "") scope.set_tag("channel", ctx.channel.id if ctx.channel else "") scope.set_tag( "user", f"{ctx.author.name}#{ctx.author.discriminator}" if ctx.author else "") raise error_to_display
def update_info(self): res = self.calculation_manager.get_results() for el in res.errors: if el[0]: QListWidgetItem(el[0], self.logs) ExceptionListItem(el[1], self.logs) if (state_store.report_errors and parsed_version.is_devrelease and not isinstance(el[1][0], SegmentationLimitException) and isinstance(el[1][1], tuple)): with sentry_sdk.push_scope() as scope: scope.set_tag("auto_report", "true") sentry_sdk.capture_event(el[1][1][0]) self.whole_progress.setValue(res.global_counter) working_search = True for i, (progress, total) in enumerate(res.jobs_status): if working_search and progress != total: self.part_progress.setMaximum(total) self.part_progress.setValue(progress) working_search = False if i < self.task_que.count(): item = self.task_que.item(i) item.setText("Task {} ({}/{})".format(i, progress, total)) else: self.task_que.addItem("Task {} ({}/{})".format( i, progress, total)) if not self.calculation_manager.has_work: print( "[ProgressView.update_info]", self.calculation_manager.has_work, self.calculation_manager.batch_manager.has_work, self.calculation_manager.writer.writing_finished(), ) self.part_progress.setValue(self.part_progress.maximum()) self.preview_timer.stop() logging.info("Progress stop")
def errorRaisedSubscriber(event): exc_info = ( sys.exc_info() ) # Save exc_info before new exceptions (CannotGetPortalError) arise try: error_log = api.portal.get_tool(name="error_log") except CannotGetPortalError: # Try to get Zope root. try: error_log = event.request.PARENTS[0].error_log except (AttributeError, KeyError, IndexError): error_log = None if error_log and exc_info[0].__name__ in error_log._ignored_exceptions: return with sentry_sdk.push_scope() as scope: scope.set_extra("other", _get_other_from_request(event.request)) scope.set_extra("lazy items", _get_lazyitems_from_request(event.request)) scope.set_extra("cookies", _get_cookies_from_request(event.request)) scope.set_extra("form", _get_form_from_request(event.request)) scope.set_extra("request", _get_request_from_request(event.request)) user_info = _get_user_from_request(event.request) scope.set_extra("user", user_info) if user_info and "id" in user_info: scope.user = user_info sentry_sdk.capture_exception(exc_info)
def raising(self, info): """ Log an exception and send the info to sentry """ exc_info = sys.exc_info() res = SiteErrorLog.raising(self, info) send_anyway = os.environ.get(SEND_ANYWAY_ENV_VAR, '') if getConfiguration().debug_mode and not send_anyway: # We are in debug mode, do not send tb to Sentry logger.info('Zope is in debug mode. Not sending error to sentry') return res dsn = self.getsentry_dsn dsn = dsn and dsn or os.environ.get(DSN_ENV_VAR, '') if not dsn: logger.warning('Missing DSN. Unable to send errors to sentry') return res if res is not None: client = get_or_create_client(dsn) event, hint = event_from_exception(exc_info, client_options=client.options) hub = Hub.current hub.start_session() with sentry_sdk.push_scope() as scope: request = getattr(self, 'REQUEST', None) if not request: request = getRequest() _prepare_scope_and_event(request, scope, event) sentry_sdk.capture_event(event, hint, scope) hub.end_session() return res
def _handle_consume_exception(self, events: List[Dict[str, Any]], exception: Exception) -> None: with configure_scope() as scope: scope.set_context("events", { "data": events, "queue_name": self.queue_name, }) if isinstance(exception, WorkerTimeoutException): with sentry_sdk.push_scope() as scope: scope.fingerprint = ['worker-timeout', self.queue_name] logging.exception("%s in queue %s", str(exception), self.queue_name, stack_info=True) else: logging.exception("Problem handling data on queue %s", self.queue_name, stack_info=True) if not os.path.exists(settings.QUEUE_ERROR_DIR): os.mkdir(settings.QUEUE_ERROR_DIR) # nocoverage # Use 'mark_sanitized' to prevent Pysa from detecting this false positive # flow. 'queue_name' is always a constant string. fname = mark_sanitized(f'{self.queue_name}.errors') fn = os.path.join(settings.QUEUE_ERROR_DIR, fname) line = f'{time.asctime()}\t{orjson.dumps(events).decode()}\n' lock_fn = fn + '.lock' with lockfile(lock_fn): with open(fn, 'a') as f: f.write(line) check_and_send_restart_signal()
async def handle_unexpected_error(ctx: Context, e: errors.CommandError) -> None: """Send a generic error message in `ctx` and log the exception as an error with exc_info.""" await ctx.send( f"Sorry, an unexpected error occurred. Please let us know!\n\n" f"```{e.__class__.__name__}: {e}```") ctx.bot.stats.incr("errors.unexpected") with push_scope() as scope: scope.user = {"id": ctx.author.id, "username": str(ctx.author)} scope.set_tag("command", ctx.command.qualified_name) scope.set_tag("message_id", ctx.message.id) scope.set_tag("channel_id", ctx.channel.id) scope.set_extra("full_message", ctx.message.content) if ctx.guild is not None: scope.set_extra( "jump_to", f"https://discordapp.com/channels/{ctx.guild.id}/{ctx.channel.id}/{ctx.message.id}" ) log.error( f"Error executing command invoked by {ctx.message.author}: {ctx.message.content}", exc_info=e)
def get_vendor_id(self, message_id, language): req_language = language message = None language = language.strip() language = language or "en-US" exc = AcousticTxEmailMessage.DoesNotExist try: # try to get the exact language message = self.get(message_id=message_id, language=language) except exc: if "-" in language: language = language.split("-")[0] try: # failing above, try to get the language prefix message = self.get(message_id=message_id, language__startswith=language) except exc: try: # failing above, try to get the default language message = self.get(message_id=message_id, language="en-US") except exc: # couldn't find a message. give up. with sentry_sdk.push_scope() as scope: scope.set_tag("language", req_language) scope.set_tag("message_id", message_id) sentry_sdk.capture_exception() if message: return message.vendor_id
def register_error(self, event_method: str, error: Exception, ctx: Optional[commands.Context] = None): if configuration['sentry_dsn'] is None: traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) else: with sentry_sdk.push_scope() as scope: scope.set_tag('event_method', event_method) if ctx is not None: scope.user = { 'id': ctx.author.id, 'username': str(ctx.author), 'activities': ( ', '.join((str(activity) for activity in ctx.author.activities if activity)) if isinstance(ctx.author, discord.Member) else None ), } scope.set_tag('full_command', ctx.command.qualified_name) scope.set_tag('root_command', str(ctx.command.root_parent or ctx.command.qualified_name)) scope.set_context( 'message', { 'prefix': ctx.prefix, 'content': ctx.message.content, 'attachments': ', '.join((attachment.url for attachment in ctx.message.attachments)), }, ) scope.set_context('channel', {'id': ctx.channel.id, 'name': str(ctx.channel)}) if ctx.guild is not None: scope.set_context('server', {'id': ctx.guild.id, 'name': str(ctx.guild)}) sentry_sdk.capture_exception(error)
def report_error( error, request=None, extra_data=None, level='warning', prefix='Handled exception', skip_sentry=False, print_tb=False, logger=None, ): """Wrapper for error reporting. This can be used for store exceptions in error reporting solutions as rollbar while handling error gracefully and giving user cleaner message. """ if logger is None: logger = LOGGER if HAS_ROLLBAR and hasattr(settings, 'ROLLBAR'): rollbar.report_exc_info(request=request, extra_data=extra_data, level=level) if not skip_sentry and settings.SENTRY_DSN: with sentry_sdk.push_scope() as scope: if extra_data: for key, value in extra_data.items(): scope.set_extra(key, value) sentry_sdk.capture_exception() logger.error('%s: %s: %s', prefix, error.__class__.__name__, force_text(error)) if extra_data: logger.error( '%s: %s: %s', prefix, error.__class__.__name__, force_text(extra_data) ) if print_tb: logger.exception(prefix)
def log_replay_error(retry_state): """Log a replay error to sentry""" exc = retry_state.outcome.exception() with push_scope() as scope: scope.set_tag("operation", retry_state.fn.__name__) scope.set_extra("obj_id", exc.obj_id) capture_exception(exc.exc) error_context = { "obj_id": exc.obj_id, "operation": retry_state.fn.__name__, "exc": str(exc.exc), "retries": retry_state.attempt_number, } logger.error( "Failed operation %(operation)s on %(obj_id)s after %(retries)s" " retries: %(exc)s", error_context, ) # if we have a global error (redis) reporter if REPORTER is not None: oid = f"blob:{exc.obj_id}" msg = msgpack.dumps(error_context) REPORTER(oid, msg) return None
def _log_missing_field(source_system: str, missing_fields_notification: str): """ Log missing field information to sentry """ with push_scope() as scope: scope.set_tag('sourceSystem', source_system) scope.set_tag('problem', 'missing_field') scope.level = 'warning' capture_message(missing_fields_notification)
def check_repository(checks, repository, fake_path): context = CheckContext(repository, fake_path) for check in checks: try: for result in check(context): # skip unknown results if result.is_found is None: continue if result.is_found: log.info( "auditing.check.result_found", repo_id=repository.id, check=check.__name__, check_module=check.__module__, issue=result.issue_key, ) yield result except: log.exception( "auditing.check.error", repo_id=repository.id, check=check.__name__, check_module=check.__module__, ) with sentry_sdk.push_scope() as scope: scope.fingerprint = [check.__module__, check.__name__] sentry_sdk.capture_exception()
def send_message(args): ''' Mandatory args: message ''' margs = copy.copy(args) [ margs.pop(i) for i in ['verbose',] ] with sentry_sdk.push_scope() as local_scope: if margs.get('level', False): local_scope.level = margs.pop('level') if margs.get('request', False): local_scope.request = margs.pop('request') for k,v in margs.pop('extra', {}).items(): local_scope.set_extra(k, v) for k,v in margs.pop('tags', {}).items(): local_scope.set_tag(k, v) if margs.get('email', False): email_address= margs.pop('email') local_scope.user = { "email": email_address, } eventid = sentry_sdk.capture_event(margs) if args.get('verbose', True): if eventid: print('Sent Event ID: {}'.format(eventid)) else: print('Error sending Event "{}" !'.format(margs.message), file=sys.stderr) return eventid
def run(self): """This function perform check""" # noinspection PyBroadException if not state_store.check_for_updates: return try: if os.path.exists( os.path.join(state_store.save_folder, IGNORE_FILE)): with open(os.path.join(state_store.save_folder, IGNORE_FILE), encoding="utf-8") as f_p, suppress(ValueError): old_date = date.fromisoformat(f_p.read()) if (date.today() - old_date).days < IGNORE_DAYS: return os.remove(os.path.join(state_store.save_folder, IGNORE_FILE)) with urllib.request.urlopen( f"https://pypi.org/pypi/{self.package_name}/json" ) as r: # nosec data = json.load(r) self.release = data["info"]["version"] self.url = data["info"]["home_page"] except (KeyError, urllib.error.URLError): # pragma: no cover pass except Exception as e: # pylint: disable=W0703 with sentry_sdk.push_scope() as scope: scope.set_tag("auto_report", "true") scope.set_tag("check_version", "true") sentry_sdk.capture_exception(e)
def log(self, out, err, returncode): if returncode == 0: return tags = self.opts.tags or {} tags.update({'returncode': returncode, 'callable': self.args[0]}) extra = self.opts.extra or {} extra.update({ 'returncode': returncode, 'command': self.get_command(), }) extra.update(string_to_chunks('stdout', out.rstrip())) extra.update(string_to_chunks('stderr', err.rstrip())) capture_message_kwargs = dict( message=self.get_raven_message(returncode), level=logging.ERROR, tags=tags, extra=extra, ) if self.opts.debug: pprint(capture_message_kwargs) else: with sentry_sdk.push_scope() as scope: for k, v in iteritems(extra): scope.set_extra(k, v) for k, v in iteritems(tags): scope.set_tag(k, v) sentry_sdk.capture_message( capture_message_kwargs["message"], level=capture_message_kwargs["level"])
def shell_out(cmd, shell=False, logfile=None): logging.debug("Running command %r", cmd) now = str(datetime.now()) try: output = subprocess.check_output( cmd, shell=shell, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8", errors="backslashreplace", ) if logfile: with open(logfile, "a+") as log: log.write("# " + now + "\n") log.write("# Command {cmd!r} ran successfully:".format(cmd=cmd)) log.write(output) log.write("\n\n") return output except subprocess.CalledProcessError as e: if sentry_sdk: with sentry_sdk.push_scope() as scope: scope.fingerprint = ["{{ default }}", str(cmd)] sentry_sdk.capture_exception(e) if logfile: with open(logfile, "a+") as log: log.write("# " + now + "\n") log.write("# Command {cmd!r} failed:".format(cmd=cmd)) log.write(e.output) log.write("\n\n") logging.error("Command failed (see %s at %s)", logfile, now) else: logging.error("Command failed with output %r", e.output)
def error_too_large(maximum_size: int, request_size: int) -> dict: """ Creates a 'request too big' error :type maximum_size: int :param maximum_size: Maximum content length (in bytes) :type request_size: int :param request_size: Content length of request (in bytes) :rtype: dict :return: Complete JSON-API compatible error object """ log_message = f"Request content length, [{ request_size }], is too great" app.logger.warning(log_message) # As the API handles this error through this error message, it is not reported to Sentry. # However, because it's useful for tracking, we want report it anyway. with sentry_sdk.push_scope() as scope: scope.set_extra('debug', False) sentry_sdk.capture_message(log_message) return { 'id': uuid4(), 'status': HTTPStatus.REQUEST_ENTITY_TOO_LARGE, 'title': 'Request content length is too great', 'detail': 'Check the content length of the request is less than the maximum allowed', 'meta': { 'maximum_content_length_allowed': maximum_size, 'request_content_length': request_size, 'content_length_units': 'bytes' } }
def report_error( extra_data: Optional[Dict] = None, level: str = "warning", cause: str = "Handled exception", skip_sentry: bool = False, print_tb: bool = False, ): """Wrapper for error reporting. This can be used for store exceptions in error reporting solutions as rollbar while handling error gracefully and giving user cleaner message. """ if HAS_ROLLBAR and hasattr(settings, "ROLLBAR"): rollbar.report_exc_info(extra_data=extra_data, level=level) if not skip_sentry and settings.SENTRY_DSN: with sentry_sdk.push_scope() as scope: if extra_data: for key, value in extra_data.items(): scope.set_extra(key, value) scope.set_extra("error_cause", cause) scope.level = level sentry_sdk.capture_exception() log = getattr(LOGGER, level) error = sys.exc_info()[1] log("%s: %s: %s", cause, error.__class__.__name__, str(error)) if extra_data: log("%s: %s: %s", cause, error.__class__.__name__, str(extra_data)) if print_tb: LOGGER.exception(cause)
def _handle_consume_exception(self, events: List[Dict[str, Any]], exception: Exception) -> None: if isinstance(exception, InterruptConsumeException): # The exception signals that no further error handling # is needed and the worker can proceed. return with configure_scope() as scope: scope.set_context( "events", { "data": events, "queue_name": self.queue_name, }, ) if isinstance(exception, WorkerTimeoutException): with sentry_sdk.push_scope() as scope: scope.fingerprint = ["worker-timeout", self.queue_name] logging.exception(exception, stack_info=True) else: logging.exception("Problem handling data on queue %s", self.queue_name, stack_info=True) if not os.path.exists(settings.QUEUE_ERROR_DIR): os.mkdir(settings.QUEUE_ERROR_DIR) # nocoverage # Use 'mark_sanitized' to prevent Pysa from detecting this false positive # flow. 'queue_name' is always a constant string. fname = mark_sanitized(f"{self.queue_name}.errors") fn = os.path.join(settings.QUEUE_ERROR_DIR, fname) line = f"{time.asctime()}\t{orjson.dumps(events).decode()}\n" lock_fn = fn + ".lock" with lockfile(lock_fn): with open(fn, "a") as f: f.write(line) check_and_send_restart_signal()
def captureMessage(self, msg, **kwargs): with sentry_sdk.push_scope() as scope: self._kwargs_into_scope(scope, **kwargs) return capture_message(msg)
def captureException(self, exc_info=None, **kwargs): with sentry_sdk.push_scope() as scope: self._kwargs_into_scope(scope, **kwargs) return capture_exception(exc_info)