From 0473bd6cfe88ff742b95e06c22158a36c0bf8569 Mon Sep 17 00:00:00 2001 From: drew2a Date: Wed, 29 Dec 2021 15:12:42 +0100 Subject: [PATCH] Cancel SentryReporter singleton --- src/run_tribler.py | 29 +-- .../sentry_reporter/sentry_mixin.py | 10 +- .../sentry_reporter/sentry_reporter.py | 132 +++++----- .../tests/test_sentry_reporter.py | 240 ++++++++---------- .../components/reporter/exception_handler.py | 8 +- .../components/reporter/reporter_component.py | 4 +- src/tribler-core/tribler_core/start_core.py | 2 +- .../tribler_gui/dialogs/dialogcontainer.py | 3 + .../tribler_gui/dialogs/feedbackdialog.py | 22 +- src/tribler-gui/tribler_gui/error_handler.py | 9 +- .../tribler_gui/event_request_manager.py | 3 +- .../widgets/channelcontentswidget.py | 3 + .../widgets/channeldescriptionwidget.py | 3 + .../tribler_gui/widgets/createtorrentpage.py | 2 + .../tribler_gui/widgets/discoveringpage.py | 3 + .../tribler_gui/widgets/downloadspage.py | 3 + .../tribler_gui/widgets/ipv8health.py | 2 + .../tribler_gui/widgets/loadingpage.py | 3 + .../widgets/searchresultswidget.py | 3 + .../tribler_gui/widgets/settingspage.py | 3 + .../widgets/subscriptionswidget.py | 2 + .../tribler_gui/widgets/tabbuttonpanel.py | 4 +- .../tribler_gui/widgets/trustgraphpage.py | 2 + .../tribler_gui/widgets/trustpage.py | 3 + 24 files changed, 256 insertions(+), 242 deletions(-) diff --git a/src/run_tribler.py b/src/run_tribler.py index d74678a84f4..9c868b8ff13 100644 --- a/src/run_tribler.py +++ b/src/run_tribler.py @@ -2,11 +2,9 @@ # A fix for "LookupError: unknown encoding: idna" error. # Adding encodings.idna to hiddenimports is not enough. # https://github.com/pyinstaller/pyinstaller/issues/1113 -import encodings.idna # pylint: disable=unused-import import logging.config import os import sys -from enum import Enum, auto from PyQt5.QtCore import QSettings @@ -15,11 +13,12 @@ from tribler_common.sentry_reporter.sentry_reporter import SentryReporter, SentryStrategy from tribler_common.sentry_reporter.sentry_scrubber import SentryScrubber from tribler_common.version_manager import VersionHistory - from tribler_core import start_core - +from tribler_core.components.reporter.exception_handler import default_core_exception_handler logger = logging.getLogger(__name__) + + # pylint: disable=import-outside-toplevel, ungrouped-imports @@ -38,20 +37,21 @@ def init_sentry_reporter(): as a URL for sending sentry's reports while a Tribler client running in test mode """ + sentry_reporter = default_core_exception_handler.sentry_reporter from tribler_core.version import sentry_url, version_id - test_sentry_url = SentryReporter.get_test_sentry_url() + test_sentry_url = sentry_reporter.get_test_sentry_url() if not test_sentry_url: - SentryReporter.init(sentry_url=sentry_url, - release_version=version_id, - scrubber=SentryScrubber(), - strategy=SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION) + sentry_reporter.init(sentry_url=sentry_url, + release_version=version_id, + scrubber=SentryScrubber(), + strategy=SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION) logger.info('Sentry has been initialised in normal mode') else: - SentryReporter.init(sentry_url=test_sentry_url, - release_version=version_id, - scrubber=None, - strategy=SentryStrategy.SEND_ALLOWED) + sentry_reporter.init(sentry_url=test_sentry_url, + release_version=version_id, + scrubber=None, + strategy=SentryStrategy.SEND_ALLOWED) logger.info('Sentry has been initialised in debug mode') @@ -99,7 +99,6 @@ def init_boot_logger(): process_checker.remove_lock_file() else: - import tribler_gui from tribler_gui.utilities import get_translator logger.info('Running GUI' + ' in gui_test_mode' if parsed_args.gui_test_mode else '') @@ -182,5 +181,5 @@ def init_boot_logger(): for handler in logging.getLogger().handlers: handler.flush() - SentryReporter.global_strategy = SentryStrategy.SEND_SUPPRESSED + default_core_exception_handler.sentry_reporter.global_strategy = SentryStrategy.SEND_SUPPRESSED raise diff --git a/src/tribler-common/tribler_common/sentry_reporter/sentry_mixin.py b/src/tribler-common/tribler_common/sentry_reporter/sentry_mixin.py index d5b0ce443d7..01c15ef7519 100644 --- a/src/tribler-common/tribler_common/sentry_reporter/sentry_mixin.py +++ b/src/tribler-common/tribler_common/sentry_reporter/sentry_mixin.py @@ -1,3 +1,5 @@ +from typing import Optional + from tribler_common.sentry_reporter.sentry_reporter import SentryReporter @@ -6,7 +8,13 @@ class AddBreadcrumbOnShowMixin: and send breadcrumbs on a show event. """ + def __init__(self): + self.sentry_reporter: Optional[SentryReporter] = None + + def set_sentry_reporter(self, sentry_reporter: SentryReporter): + self.sentry_reporter = sentry_reporter + def showEvent(self, *args): super().showEvent(*args) - SentryReporter.add_breadcrumb(message=f'{self.__class__.__name__}.Show', category='UI', level='info') + self.sentry_reporter.add_breadcrumb(message=f'{self.__class__.__name__}.Show', category='UI', level='info') diff --git a/src/tribler-common/tribler_common/sentry_reporter/sentry_reporter.py b/src/tribler-common/tribler_common/sentry_reporter/sentry_reporter.py index 0aa9acb8235..b4e55ee9071 100644 --- a/src/tribler-common/tribler_common/sentry_reporter/sentry_reporter.py +++ b/src/tribler-common/tribler_common/sentry_reporter/sentry_reporter.py @@ -5,10 +5,10 @@ from contextvars import ContextVar from enum import Enum, auto from hashlib import md5 - -from faker import Faker +from typing import Dict, List, Optional import sentry_sdk +from faker import Faker from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger from sentry_sdk.integrations.threading import ThreadingIntegration @@ -54,13 +54,13 @@ class SentryStrategy(Enum): @contextmanager -def this_sentry_strategy(strategy: SentryStrategy): - saved_strategy = SentryReporter.thread_strategy.get() +def this_sentry_strategy(reporter, strategy: SentryStrategy): + saved_strategy = reporter.thread_strategy.get() try: - SentryReporter.thread_strategy.set(strategy) - yield + reporter.thread_strategy.set(strategy) + yield reporter finally: - SentryReporter.thread_strategy.set(saved_strategy) + reporter.thread_strategy.set(saved_strategy) class SentryReporter: @@ -68,19 +68,20 @@ class SentryReporter: a Tribler Client. """ - scrubber = None - last_event = None - ignored_exceptions = [KeyboardInterrupt, SystemExit] - # more info about how SentryReporter choose a strategy see in - # SentryReporter.get_actual_strategy() - global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - thread_strategy = ContextVar('context_strategy', default=None) + def __init__(self): + self.scrubber = None + self.last_event = None + self.ignored_exceptions = [KeyboardInterrupt, SystemExit] + # more info about how SentryReporter choose a strategy see in + # SentryReporter.get_actual_strategy() + self.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION + self.thread_strategy = ContextVar('context_strategy', default=None) - _sentry_logger_name = 'SentryReporter' - _logger = logging.getLogger(_sentry_logger_name) + self._sentry_logger_name = 'SentryReporter' + self._logger = logging.getLogger(self._sentry_logger_name) - @staticmethod - def init(sentry_url='', release_version='', scrubber=None, strategy=SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION): + def init(self, sentry_url='', release_version='', scrubber=None, + strategy=SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION): """Initialization. This method should be called in each process that uses SentryReporter. @@ -102,9 +103,9 @@ def scrub_event(self, event): Returns: Sentry Guard. """ - SentryReporter._logger.debug(f"Init: {sentry_url}") - SentryReporter.scrubber = scrubber - SentryReporter.global_strategy = strategy + self._logger.debug(f"Init: {sentry_url}") + self.scrubber = scrubber + self.global_strategy = strategy rv = sentry_sdk.init( sentry_url, @@ -117,21 +118,19 @@ def scrub_event(self, event): ), ThreadingIntegration(propagate_hub=True), ], - before_send=SentryReporter._before_send, + before_send=self._before_send, ignore_errors=[KeyboardInterrupt], ) - ignore_logger(SentryReporter._sentry_logger_name) + ignore_logger(self._sentry_logger_name) return rv - @staticmethod - def ignore_logger(logger_name): - SentryReporter._logger.debug(f"Ignore logger: {logger_name}") + def ignore_logger(self, logger_name: str): + self._logger.debug(f"Ignore logger: {logger_name}") ignore_logger(logger_name) - @staticmethod - def add_breadcrumb(message='', category='', level='info', **kwargs): + def add_breadcrumb(self, message='', category='', level='info', **kwargs): """Adds a breadcrumb for current Sentry client. It is necessary to specify a message, a category and a level to make this @@ -142,13 +141,12 @@ def add_breadcrumb(message='', category='', level='info', **kwargs): """ crumb = {'message': message, 'category': category, 'level': level} - SentryReporter._logger.debug(f"Add the breadcrumb: {crumb}") + self._logger.debug(f"Add the breadcrumb: {crumb}") return sentry_sdk.add_breadcrumb(crumb, **kwargs) - @staticmethod - def send_event(event=None, post_data=None, sys_info=None, additional_tags=None, - retrieve_error_message_from_stacktrace=False): + def send_event(self, event: Dict = None, post_data: Dict = None, sys_info: Dict = None, + additional_tags: List[str] = None, retrieve_error_message_from_stacktrace=False): """Send the event to the Sentry server This method @@ -172,7 +170,7 @@ def send_event(event=None, post_data=None, sys_info=None, additional_tags=None, Returns: Event that was sent to Sentry server """ - SentryReporter._logger.info(f"Send: {post_data}, {event}") + self._logger.info(f"Send: {post_data}, {event}") if event is None: return event @@ -229,13 +227,12 @@ def send_event(event=None, post_data=None, sys_info=None, additional_tags=None, 'value': exception_value[1] }) - with this_sentry_strategy(SentryStrategy.SEND_ALLOWED): + with this_sentry_strategy(self, SentryStrategy.SEND_ALLOWED): sentry_sdk.capture_event(event) return event - @staticmethod - def get_confirmation(exception): + def get_confirmation(self, exception): """Get confirmation on sending exception to the Team. There are two message boxes, that will be triggered: @@ -251,10 +248,10 @@ def get_confirmation(exception): try: from PyQt5.QtWidgets import QApplication, QMessageBox except ImportError: - SentryReporter._logger.debug("PyQt5 is not available. User confirmation is not possible.") + self._logger.debug("PyQt5 is not available. User confirmation is not possible.") return False - SentryReporter._logger.debug(f"Get confirmation: {exception}") + self._logger.debug(f"Get confirmation: {exception}") _ = QApplication(sys.argv) messagebox = QMessageBox(icon=QMessageBox.Critical, text=f'{exception}.') @@ -271,13 +268,11 @@ def get_confirmation(exception): return messagebox.exec() == QMessageBox.Yes - @staticmethod - def capture_exception(exception): - SentryReporter._logger.info(f"Capture exception: {exception}") + def capture_exception(self, exception): + self._logger.info(f"Capture exception: {exception}") sentry_sdk.capture_exception(exception) - @staticmethod - def event_from_exception(exception): + def event_from_exception(self, exception) -> Dict: """This function format the exception by passing it through sentry Args: exception: an exception that will be passed to `sentry_sdk.capture_exception(exception)` @@ -285,17 +280,16 @@ def event_from_exception(exception): Returns: the event that has been saved in `_before_send` method """ - SentryReporter._logger.info(f"Event from exception: {exception}") + self._logger.info(f"Event from exception: {exception}") if not exception: - return exception + return {} - with this_sentry_strategy(SentryStrategy.SEND_SUPPRESSED): + with this_sentry_strategy(self, SentryStrategy.SEND_SUPPRESSED): sentry_sdk.capture_exception(exception) - return SentryReporter.last_event + return self.last_event - @staticmethod - def set_user(user_id): + def set_user(self, user_id): """Set the user to identify the event on a Sentry server The algorithm is the following: @@ -313,7 +307,7 @@ def set_user(user_id): # calculate hash to keep real `user_id` in secret user_id_hash = md5(user_id).hexdigest() - SentryReporter._logger.debug(f"Set user: {user_id_hash}") + self._logger.debug(f"Set user: {user_id_hash}") Faker.seed(user_id_hash) user_name = Faker().name() @@ -322,17 +316,16 @@ def set_user(user_id): sentry_sdk.set_user(user) return user - @staticmethod - def get_actual_strategy(): + def get_actual_strategy(self): """This method is used to determine actual strategy. - Strategy can be global: SentryReporter.strategy - and local: SentryReporter._context_strategy. + Strategy can be global: self.strategy + and local: self._context_strategy. Returns: the local strategy if it is defined, the global strategy otherwise """ - strategy = SentryReporter.thread_strategy.get() - return strategy if strategy else SentryReporter.global_strategy + strategy = self.thread_strategy.get() + return strategy if strategy else self.global_strategy @staticmethod def get_test_sentry_url(): @@ -342,15 +335,14 @@ def get_test_sentry_url(): def is_in_test_mode(): return bool(SentryReporter.get_test_sentry_url()) - @staticmethod - def _before_send(event, hint): + def _before_send(self, event: Dict, hint: Dict) -> Optional[Dict]: """The method that is called before each send. Both allowed and disallowed. The algorithm: 1. If sending is allowed, then scrub the event and send. 2. If sending is disallowed, then store the event in - `SentryReporter.last_event` + `self.last_event` Args: event: event that generated by Sentry @@ -363,30 +355,30 @@ def _before_send(event, hint): return event # trying to get context-depending strategy first - strategy = SentryReporter.get_actual_strategy() + strategy = self.get_actual_strategy() - SentryReporter._logger.info(f"Before send strategy: {strategy}") + self._logger.info(f"Before send strategy: {strategy}") exc_info = get_value(hint, 'exc_info') error_type = get_first_item(exc_info) - if error_type in SentryReporter.ignored_exceptions: - SentryReporter._logger.debug(f"Exception is in ignored: {hint}. Skipped.") + if error_type in self.ignored_exceptions: + self._logger.debug(f"Exception is in ignored: {hint}. Skipped.") return None if strategy == SentryStrategy.SEND_SUPPRESSED: - SentryReporter._logger.debug("Suppress sending. Storing the event.") - SentryReporter.last_event = event + self._logger.debug("Suppress sending. Storing the event.") + self.last_event = event return None if strategy == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION: - SentryReporter._logger.debug("Request confirmation.") - if not SentryReporter.get_confirmation(hint): + self._logger.debug("Request confirmation.") + if not self.get_confirmation(hint): return None # clean up the event - SentryReporter._logger.debug(f"Clean up the event with scrubber: {SentryReporter.scrubber}") - if SentryReporter.scrubber: - event = SentryReporter.scrubber.scrub_event(event) + self._logger.debug(f"Clean up the event with scrubber: {self.scrubber}") + if self.scrubber: + event = self.scrubber.scrub_event(event) return event diff --git a/src/tribler-common/tribler_common/sentry_reporter/tests/test_sentry_reporter.py b/src/tribler-common/tribler_common/sentry_reporter/tests/test_sentry_reporter.py index 4fe88b5cc2c..99a68aab72d 100644 --- a/src/tribler-common/tribler_common/sentry_reporter/tests/test_sentry_reporter.py +++ b/src/tribler-common/tribler_common/sentry_reporter/tests/test_sentry_reporter.py @@ -11,42 +11,34 @@ # fmt: off +# pylint: disable=redefined-outer-name, protected-access -@pytest.fixture(name="mock_reporter") # this workaround implemented only for pylint -def fixture_mock_reporter(): - class MockReporter: - def __init__(self): - self._allow_sending = None - def get_allow_sending(self): - return self._allow_sending +@pytest.fixture +def sentry_reporter(): + return SentryReporter() - def allow_sending(self, value, _=None): - self._allow_sending = value - return MockReporter() +def test_init(sentry_reporter): + assert sentry_reporter.init('') -def test_init(): - assert SentryReporter.init('') - - -def test_set_user(): - assert SentryReporter.set_user(b'some_id') == { +def test_set_user(sentry_reporter): + assert sentry_reporter.set_user(b'some_id') == { 'id': 'db69fe66ec6b6b013c2f7d271ce17cae', 'username': 'Wanda Brown', } - assert SentryReporter.set_user(b'11111100100') == { + assert sentry_reporter.set_user(b'11111100100') == { 'id': '91f900f528d5580581197c2c6a4adbbc', 'username': 'Jennifer Herrera', } -def test_send_defaults(): - assert SentryReporter.send_event(None, None, None) is None +def test_send_defaults(sentry_reporter): + assert sentry_reporter.send_event(None, None, None) is None - assert SentryReporter.send_event(event={}) == { + assert sentry_reporter.send_event(event={}) == { 'contexts': { 'browser': {'name': 'Tribler', 'version': None}, 'reporter': { @@ -63,69 +55,58 @@ def test_send_defaults(): } -def test_send_post_data(): - assert SentryReporter.send_event( - event={'a': 'b'}, - post_data={ - "version": '0.0.0', - "machine": 'x86_64', - "os": 'posix', - "timestamp": 42, - "sysinfo": '', - "comments": 'comment', - "stack": 'l1\nl2--LONG TEXT--l3\nl4', +def test_send_post_data(sentry_reporter): + actual = sentry_reporter.send_event(event={'a': 'b'}, + post_data={"version": '0.0.0', "machine": 'x86_64', "os": 'posix', + "timestamp": 42, "sysinfo": '', "comments": 'comment', + "stack": 'l1\nl2--LONG TEXT--l3\nl4', }, ) + expected = { + 'a': 'b', + 'contexts': { + 'browser': {'name': 'Tribler', 'version': '0.0.0'}, + 'reporter': { + '_stacktrace': ['l1', 'l2'], + '_stacktrace_context': [], + '_stacktrace_extra': ['l3', 'l4'], + 'comments': 'comment', + 'os.environ': {}, + 'sysinfo': {}, + 'events': {}, + }, }, - ) == { - 'a': 'b', - 'contexts': { - 'browser': {'name': 'Tribler', 'version': '0.0.0'}, - 'reporter': { - '_stacktrace': ['l1', 'l2'], - '_stacktrace_context': [], - '_stacktrace_extra': ['l3', 'l4'], - 'comments': 'comment', - 'os.environ': {}, - 'sysinfo': {}, - 'events': {}, - }, - }, - 'tags': {'machine': 'x86_64', 'os': 'posix', 'platform': None, PLATFORM_DETAILS: None, - 'version': '0.0.0'}, - } - - -def test_send_sys_info(): - assert SentryReporter.send_event( - event={}, - sys_info={ - 'platform': ['darwin'], - PLATFORM_DETAILS: ['details'], - OS_ENVIRON: ['KEY:VALUE', 'KEY1:VALUE1'], - 'event_1': [{'type': ''}], - 'request_1': [{}], - 'event_2': [], - 'request_2': [], + 'tags': {'machine': 'x86_64', 'os': 'posix', 'platform': None, PLATFORM_DETAILS: None, + 'version': '0.0.0'}, + } + assert actual == expected + + +def test_send_sys_info(sentry_reporter): + actual = sentry_reporter.send_event(event={}, sys_info={'platform': ['darwin'], PLATFORM_DETAILS: ['details'], + OS_ENVIRON: ['KEY:VALUE', 'KEY1:VALUE1'], + 'event_1': [{'type': ''}], 'request_1': [{}], 'event_2': [], + 'request_2': [], }, ) + expected = { + 'contexts': { + 'browser': {'name': 'Tribler', 'version': None}, + 'reporter': { + '_stacktrace': [], + '_stacktrace_context': [], + '_stacktrace_extra': [], + 'comments': None, + OS_ENVIRON: {'KEY': 'VALUE', 'KEY1': 'VALUE1'}, + 'sysinfo': {'platform': ['darwin'], PLATFORM_DETAILS: ['details']}, + 'events': {'event_1': [{'type': ''}], 'request_1': [{}], 'event_2': [], 'request_2': []}, + }, }, - ) == { - 'contexts': { - 'browser': {'name': 'Tribler', 'version': None}, - 'reporter': { - '_stacktrace': [], - '_stacktrace_context': [], - '_stacktrace_extra': [], - 'comments': None, - OS_ENVIRON: {'KEY': 'VALUE', 'KEY1': 'VALUE1'}, - 'sysinfo': {'platform': ['darwin'], PLATFORM_DETAILS: ['details']}, - 'events': {'event_1': [{'type': ''}], 'request_1': [{}], 'event_2': [], 'request_2': []}, - }, - }, - 'tags': {'machine': None, 'os': None, 'platform': 'darwin', 'platform.details': 'details', - 'version': None}, - } - - -def test_send_additional_tags(): - assert SentryReporter.send_event(event={}, additional_tags={'tag_key': 'tag_value'}) == { + 'tags': {'machine': None, 'os': None, 'platform': 'darwin', 'platform.details': 'details', + 'version': None}, + } + assert actual == expected + + +def test_send_additional_tags(sentry_reporter): + actual = sentry_reporter.send_event(event={}, additional_tags={'tag_key': 'tag_value'}) + expected = { 'contexts': { 'browser': {'name': 'Tribler', 'version': None}, 'reporter': { @@ -147,94 +128,91 @@ def test_send_additional_tags(): 'tag_key': 'tag_value', }, } + assert actual == expected -def test_before_send(): - SentryReporter.thread_strategy.set(None) # default +def test_before_send(sentry_reporter): + sentry_reporter.thread_strategy.set(None) # default scrubber = SentryScrubber() - SentryReporter.init('', scrubber=scrubber) - - # pylint: disable=protected-access - SentryReporter.last_event = None + sentry_reporter.init('', scrubber=scrubber) + sentry_reporter.last_event = None - assert SentryReporter._before_send({}, {}) == {} - assert SentryReporter._before_send(None, {}) is None - assert SentryReporter._before_send(None, None) is None + assert sentry_reporter._before_send({}, {}) == {} + assert sentry_reporter._before_send(None, {}) is None + assert sentry_reporter._before_send(None, None) is None - SentryReporter.global_strategy = SentryStrategy.SEND_SUPPRESSED - assert SentryReporter.last_event is None + sentry_reporter.global_strategy = SentryStrategy.SEND_SUPPRESSED + assert sentry_reporter.last_event is None # check that an event is stored - assert SentryReporter._before_send({'a': 'b'}, None) is None - assert SentryReporter.last_event == {'a': 'b'} + assert sentry_reporter._before_send({'a': 'b'}, None) is None + assert sentry_reporter.last_event == {'a': 'b'} # check an event has been processed - SentryReporter.global_strategy = SentryStrategy.SEND_ALLOWED - assert SentryReporter._before_send({'c': 'd'}, None) == {'c': 'd'} - assert SentryReporter.last_event == {'a': 'b'} + sentry_reporter.global_strategy = SentryStrategy.SEND_ALLOWED + assert sentry_reporter._before_send({'c': 'd'}, None) == {'c': 'd'} + assert sentry_reporter.last_event == {'a': 'b'} # check that event can be ignored - assert SentryReporter._before_send({'a': 'b'}, {'exc_info': [KeyboardInterrupt]}) is None + assert sentry_reporter._before_send({'a': 'b'}, {'exc_info': [KeyboardInterrupt]}) is None # check information has been scrubbed - assert SentryReporter._before_send({'contexts': {'reporter': {'_stacktrace': ['/Users/username/']}}}, None) == { + assert sentry_reporter._before_send({'contexts': {'reporter': {'_stacktrace': ['/Users/username/']}}}, None) == { 'contexts': {'reporter': {'_stacktrace': [f'/Users/{scrubber.placeholder_user}/']}} } # check release - assert SentryReporter._before_send({'release': '7.6.0'}, None) == {'release': '7.6.0'} - assert SentryReporter._before_send({'release': '7.6.0-GIT'}, None) == {'release': None} + assert sentry_reporter._before_send({'release': '7.6.0'}, None) == {'release': '7.6.0'} + assert sentry_reporter._before_send({'release': '7.6.0-GIT'}, None) == {'release': None} # check confirmation - SentryReporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - SentryReporter.get_confirmation = lambda e: False - assert SentryReporter._before_send({'a': 'b'}, None) is None - - SentryReporter.get_confirmation = lambda e: True - assert SentryReporter._before_send({'a': 'b'}, None) == {'a': 'b'} + sentry_reporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION + sentry_reporter.get_confirmation = lambda e: False + assert sentry_reporter._before_send({'a': 'b'}, None) is None + sentry_reporter.get_confirmation = lambda e: True + assert sentry_reporter._before_send({'a': 'b'}, None) == {'a': 'b'} -def test_event_from_exception(): - assert not SentryReporter.event_from_exception(None) +def test_event_from_exception(sentry_reporter): + assert not sentry_reporter.event_from_exception(None) # sentry sdk is not initialised, so None will be returned - SentryReporter.last_event = None - assert not SentryReporter.event_from_exception(Exception('test')) + assert not sentry_reporter.event_from_exception(Exception('test')) -def test_add_breadcrumb(): +def test_add_breadcrumb(sentry_reporter): # test: None does not produce error - assert SentryReporter.add_breadcrumb(None, None, None) is None - assert SentryReporter.add_breadcrumb('message', 'category', 'level') is None - assert SentryReporter.add_breadcrumb('message', 'category', 'level', named_arg='some') is None + assert sentry_reporter.add_breadcrumb(None, None, None) is None + assert sentry_reporter.add_breadcrumb('message', 'category', 'level') is None + assert sentry_reporter.add_breadcrumb('message', 'category', 'level', named_arg='some') is None -def test_sentry_strategy(): - SentryReporter.thread_strategy.set(None) # default - SentryReporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION +def test_sentry_strategy(sentry_reporter): + sentry_reporter.thread_strategy.set(None) # default + sentry_reporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - with this_sentry_strategy(SentryStrategy.SEND_ALLOWED): - assert SentryReporter.global_strategy == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - assert SentryReporter.thread_strategy.get() == SentryStrategy.SEND_ALLOWED + with this_sentry_strategy(sentry_reporter, SentryStrategy.SEND_ALLOWED) as reporter: + assert reporter.global_strategy == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION + assert reporter.thread_strategy.get() == SentryStrategy.SEND_ALLOWED - assert SentryReporter.thread_strategy.get() is None - assert SentryReporter.global_strategy == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION + assert sentry_reporter.thread_strategy.get() is None + assert sentry_reporter.global_strategy == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION -def test_get_actual_strategy(): - SentryReporter.thread_strategy.set(None) # default - SentryReporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION +def test_get_actual_strategy(sentry_reporter): + sentry_reporter.thread_strategy.set(None) # default + sentry_reporter.global_strategy = SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - assert SentryReporter.get_actual_strategy() == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION + assert sentry_reporter.get_actual_strategy() == SentryStrategy.SEND_ALLOWED_WITH_CONFIRMATION - SentryReporter.thread_strategy.set(SentryStrategy.SEND_ALLOWED) - assert SentryReporter.get_actual_strategy() == SentryStrategy.SEND_ALLOWED + sentry_reporter.thread_strategy.set(SentryStrategy.SEND_ALLOWED) + assert sentry_reporter.get_actual_strategy() == SentryStrategy.SEND_ALLOWED -def test_retrieve_error_message_from_stacktrace(): +def test_retrieve_error_message_from_stacktrace(sentry_reporter): post_data = {"stack": '--LONG TEXT--Type: Text'} - event = SentryReporter.send_event({EXCEPTION: {VALUES: []}}, post_data, None, None, True) + event = sentry_reporter.send_event({EXCEPTION: {VALUES: []}}, post_data, None, None, True) assert event[EXCEPTION][VALUES][0]['type'] == 'Type' assert event[EXCEPTION][VALUES][0]['value'] == ' Text' diff --git a/src/tribler-core/tribler_core/components/reporter/exception_handler.py b/src/tribler-core/tribler_core/components/reporter/exception_handler.py index e28f1d160ca..d4c6f7e34f1 100644 --- a/src/tribler-core/tribler_core/components/reporter/exception_handler.py +++ b/src/tribler-core/tribler_core/components/reporter/exception_handler.py @@ -9,7 +9,6 @@ from tribler_common.reported_error import ReportedError from tribler_common.sentry_reporter.sentry_reporter import SentryReporter - from tribler_core.components.base import ComponentStartupException # There are some errors that we are ignoring. @@ -41,6 +40,7 @@ def __init__(self): self.logger = logging.getLogger("CoreExceptionHandler") self.report_callback: Optional[Callable[[ReportedError], None]] = None self.unreported_error: Optional[ReportedError] = None + self.sentry_reporter = SentryReporter() @staticmethod def _get_long_text_from(exception: Exception): @@ -73,7 +73,7 @@ def unhandled_error_observer(self, _, context): It broadcasts the tribler_exception event. """ try: - SentryReporter.ignore_logger(self.logger.name) + self.sentry_reporter.ignore_logger(self.logger.name) context = context.copy() should_stop = context.pop('should_stop', True) @@ -97,7 +97,7 @@ def unhandled_error_observer(self, _, context): text=text, long_text=long_text, context=str(context), - event=SentryReporter.event_from_exception(exception) or {}, + event=self.sentry_reporter.event_from_exception(exception) or {}, should_stop=should_stop ) if self.report_callback: @@ -110,7 +110,7 @@ def unhandled_error_observer(self, _, context): except Exception as ex: - SentryReporter.capture_exception(ex) + self.sentry_reporter.capture_exception(ex) raise ex diff --git a/src/tribler-core/tribler_core/components/reporter/reporter_component.py b/src/tribler-core/tribler_core/components/reporter/reporter_component.py index e0cf20af51b..207706a904c 100644 --- a/src/tribler-core/tribler_core/components/reporter/reporter_component.py +++ b/src/tribler-core/tribler_core/components/reporter/reporter_component.py @@ -1,6 +1,6 @@ -from tribler_common.sentry_reporter.sentry_reporter import SentryReporter from tribler_core.components.base import Component from tribler_core.components.key.key_component import KeyComponent +from tribler_core.components.reporter.exception_handler import default_core_exception_handler from tribler_core.utilities.unicode import hexlify @@ -11,4 +11,4 @@ async def run(self): return user_id_str = hexlify(key_component.primary_key.key.pk).encode('utf-8') - SentryReporter.set_user(user_id_str) + default_core_exception_handler.sentry_reporter.set_user(user_id_str) diff --git a/src/tribler-core/tribler_core/start_core.py b/src/tribler-core/tribler_core/start_core.py index a6d49d95193..cd7b81accd2 100644 --- a/src/tribler-core/tribler_core/start_core.py +++ b/src/tribler-core/tribler_core/start_core.py @@ -122,7 +122,7 @@ def run_tribler_core(api_port, api_key, state_dir, gui_test_mode=False): config.gui_test_mode = gui_test_mode if SentryReporter.is_in_test_mode(): - SentryReporter.global_strategy = SentryStrategy.SEND_ALLOWED + default_core_exception_handler.sentry_reporter.global_strategy = SentryStrategy.SEND_ALLOWED config.api.http_port = int(api_port) # If the API key is set to an empty string, it will remain disabled diff --git a/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py b/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py index 28ceed9c4df..73547c00024 100644 --- a/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py +++ b/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py @@ -3,6 +3,7 @@ from PyQt5.QtWidgets import QStyle, QStyleOption, QWidget from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect @@ -10,6 +11,8 @@ class DialogContainer(AddBreadcrumbOnShowMixin, QWidget): def __init__(self, parent, left_right_margin=100): QWidget.__init__(self, parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.setStyleSheet("background-color: rgba(30, 30, 30, 0.75);") self.dialog_widget = QWidget(self) diff --git a/src/tribler-gui/tribler_gui/dialogs/feedbackdialog.py b/src/tribler-gui/tribler_gui/dialogs/feedbackdialog.py index a5197824741..c992d07dbe2 100644 --- a/src/tribler-gui/tribler_gui/dialogs/feedbackdialog.py +++ b/src/tribler-gui/tribler_gui/dialogs/feedbackdialog.py @@ -13,7 +13,7 @@ from tribler_common.sentry_reporter.sentry_reporter import SentryReporter from tribler_common.sentry_reporter.sentry_scrubber import SentryScrubber from tribler_common.sentry_reporter.sentry_tools import CONTEXT_DELIMITER, LONG_TEXT_DELIMITER - +from tribler_gui.error_handler import ErrorHandler from tribler_gui.event_request_manager import received_events from tribler_gui.tribler_action_menu import TriblerActionMenu from tribler_gui.tribler_request_manager import performed_requests as tribler_performed_requests @@ -22,16 +22,17 @@ class FeedbackDialog(AddBreadcrumbOnShowMixin, QDialog): def __init__( # pylint: disable=too-many-arguments, too-many-locals - self, - parent, - reported_error: ReportedError, - tribler_version, - start_time, - stop_application_on_close=True, - additional_tags=None, - retrieve_error_message_from_stacktrace=False, + self, + parent, + reported_error: ReportedError, + tribler_version, + start_time, + stop_application_on_close=True, + additional_tags=None, + retrieve_error_message_from_stacktrace=False, ): QDialog.__init__(self, parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) uic.loadUi(get_ui_file_path('feedback_dialog.ui'), self) @@ -69,7 +70,6 @@ def add_item_to_info_widget(key, value): ) stacktrace = self.scrubber.scrub_text(text_for_viewing.rstrip()) self.error_text_edit.setPlainText(stacktrace) - connect(self.cancel_button.clicked, self.on_cancel_clicked) connect(self.send_report_button.clicked, self.on_send_clicked) @@ -167,7 +167,7 @@ def on_send_clicked(self, checked): "stack": stack, } - SentryReporter.send_event( + ErrorHandler.sentry_reporter.send_event( self.reported_error.event, post_data, sys_info_dict, diff --git a/src/tribler-gui/tribler_gui/error_handler.py b/src/tribler-gui/tribler_gui/error_handler.py index 7f50f053999..d7cab6d1645 100644 --- a/src/tribler-gui/tribler_gui/error_handler.py +++ b/src/tribler-gui/tribler_gui/error_handler.py @@ -3,17 +3,18 @@ from tribler_common.reported_error import ReportedError from tribler_common.sentry_reporter.sentry_reporter import SentryReporter, SentryStrategy - # fmt: off from tribler_gui.dialogs.feedbackdialog import FeedbackDialog from tribler_gui.exceptions import CoreError class ErrorHandler: + sentry_reporter = SentryReporter() + def __init__(self, tribler_window): logger_name = self.__class__.__name__ self._logger = logging.getLogger(logger_name) - SentryReporter.ignore_logger(logger_name) + ErrorHandler.sentry_reporter.ignore_logger(logger_name) self.tribler_window = tribler_window @@ -29,7 +30,7 @@ def gui_error(self, *exc_info): if self._tribler_stopped: return - if SentryReporter.global_strategy == SentryStrategy.SEND_SUPPRESSED: + if ErrorHandler.sentry_reporter.global_strategy == SentryStrategy.SEND_SUPPRESSED: self._logger.info(f'GUI error was suppressed and not sent to Sentry: {info_type.__name__}: {info_error}') return @@ -45,7 +46,7 @@ def gui_error(self, *exc_info): reported_error = ReportedError( type=type(info_type).__name__, text=text, - event=SentryReporter.event_from_exception(info_error), + event=ErrorHandler.sentry_reporter.event_from_exception(info_error), ) FeedbackDialog( diff --git a/src/tribler-gui/tribler_gui/event_request_manager.py b/src/tribler-gui/tribler_gui/event_request_manager.py index 825dcd64270..b6ff7ae5c88 100644 --- a/src/tribler-gui/tribler_gui/event_request_manager.py +++ b/src/tribler-gui/tribler_gui/event_request_manager.py @@ -8,6 +8,7 @@ from tribler_common.reported_error import ReportedError from tribler_common.sentry_reporter.sentry_reporter import SentryReporter from tribler_common.simpledefs import NTFY +from tribler_gui.error_handler import ErrorHandler from tribler_gui.exceptions import CoreConnectTimeoutError, CoreConnectionError from tribler_gui.utilities import connect @@ -72,7 +73,7 @@ def events_start_received(self, event_dict): # at the core side as well public_key = event_dict["public_key"] if public_key: - SentryReporter.set_user(public_key.encode('utf-8')) + ErrorHandler.sentry_reporter.set_user(public_key.encode('utf-8')) def on_error(self, error, reschedule_on_err): if error == QNetworkReply.ConnectionRefusedError: diff --git a/src/tribler-gui/tribler_gui/widgets/channelcontentswidget.py b/src/tribler-gui/tribler_gui/widgets/channelcontentswidget.py index 24d531d9274..17dc168d6db 100644 --- a/src/tribler-gui/tribler_gui/widgets/channelcontentswidget.py +++ b/src/tribler-gui/tribler_gui/widgets/channelcontentswidget.py @@ -21,6 +21,7 @@ ) from tribler_gui.dialogs.confirmationdialog import ConfirmationDialog from tribler_gui.dialogs.new_channel_dialog import NewChannelDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_action_menu import TriblerActionMenu from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect, disconnect, get_image_path, get_ui_file_path, tr @@ -42,6 +43,8 @@ class ChannelContentsWidget(AddBreadcrumbOnShowMixin, widget_form, widget_class): def __init__(self, parent=None): widget_class.__init__(self, parent=parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + # ACHTUNG! This is a dumb workaround for a bug(?) in PyQT bindings in Python 3.7 # When more than a single instance of a class is created, every next setupUi # triggers connectSlotsByName error. There are some reports that it is specific to diff --git a/src/tribler-gui/tribler_gui/widgets/channeldescriptionwidget.py b/src/tribler-gui/tribler_gui/widgets/channeldescriptionwidget.py index 37c8861fa65..6f66d98f61e 100644 --- a/src/tribler-gui/tribler_gui/widgets/channeldescriptionwidget.py +++ b/src/tribler-gui/tribler_gui/widgets/channeldescriptionwidget.py @@ -9,6 +9,7 @@ from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin from tribler_gui.dialogs.confirmationdialog import ConfirmationDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect, get_image_path, get_ui_file_path, tr @@ -32,6 +33,7 @@ class FloatingButtonWidget(QPushButton): def __init__(self, parent): super().__init__(QIcon(QPixmap(get_image_path('edit.png'))), "", parent) + self.setGeometry(20, 20, 20, 20) self.setFlat(True) @@ -62,6 +64,7 @@ class ChannelDescriptionWidget(AddBreadcrumbOnShowMixin, widget_form, widget_cla def __init__(self, parent=None): widget_class.__init__(self, parent=parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) try: self.setupUi(self) diff --git a/src/tribler-gui/tribler_gui/widgets/createtorrentpage.py b/src/tribler-gui/tribler_gui/widgets/createtorrentpage.py index 18eabce2e0d..3fc23ae97dd 100644 --- a/src/tribler-gui/tribler_gui/widgets/createtorrentpage.py +++ b/src/tribler-gui/tribler_gui/widgets/createtorrentpage.py @@ -8,6 +8,7 @@ from tribler_gui.defs import BUTTON_TYPE_NORMAL, PAGE_EDIT_CHANNEL_TORRENTS from tribler_gui.dialogs.confirmationdialog import ConfirmationDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_action_menu import TriblerActionMenu from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect, get_image_path @@ -20,6 +21,7 @@ class CreateTorrentPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) self.channel_identifier = None self.dialog = None diff --git a/src/tribler-gui/tribler_gui/widgets/discoveringpage.py b/src/tribler-gui/tribler_gui/widgets/discoveringpage.py index 9e66bb1b601..9ac47b61218 100644 --- a/src/tribler-gui/tribler_gui/widgets/discoveringpage.py +++ b/src/tribler-gui/tribler_gui/widgets/discoveringpage.py @@ -1,6 +1,7 @@ from PyQt5.QtWidgets import QWidget from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect from tribler_gui.widgets.loadingpage import LOADING_ANIMATION @@ -14,6 +15,8 @@ class DiscoveringPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.found_channels = 0 self.is_discovering = False diff --git a/src/tribler-gui/tribler_gui/widgets/downloadspage.py b/src/tribler-gui/tribler_gui/widgets/downloadspage.py index 2d5e43e0431..3e4c8767892 100644 --- a/src/tribler-gui/tribler_gui/widgets/downloadspage.py +++ b/src/tribler-gui/tribler_gui/widgets/downloadspage.py @@ -27,6 +27,7 @@ DOWNLOADS_FILTER_INACTIVE, ) from tribler_gui.dialogs.confirmationdialog import ConfirmationDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_action_menu import TriblerActionMenu from tribler_gui.tribler_request_manager import TriblerFileDownloadRequest, TriblerNetworkRequest from tribler_gui.utilities import compose_magnetlink, connect, format_speed, tr @@ -54,6 +55,8 @@ class DownloadsPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.export_dir = None self.filter = DOWNLOADS_FILTER_ALL self.download_widgets = {} # key: infohash, value: QTreeWidgetItem diff --git a/src/tribler-gui/tribler_gui/widgets/ipv8health.py b/src/tribler-gui/tribler_gui/widgets/ipv8health.py index 08038a8f2ad..1c3d275bd17 100644 --- a/src/tribler-gui/tribler_gui/widgets/ipv8health.py +++ b/src/tribler-gui/tribler_gui/widgets/ipv8health.py @@ -7,6 +7,7 @@ from PyQt5.QtWidgets import QWidget from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect @@ -28,6 +29,7 @@ class MonitorWidget(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): super().__init__() + self.set_sentry_reporter(ErrorHandler.sentry_reporter) self.is_paused = False diff --git a/src/tribler-gui/tribler_gui/widgets/loadingpage.py b/src/tribler-gui/tribler_gui/widgets/loadingpage.py index 78bb8e71020..db395fc2be4 100644 --- a/src/tribler-gui/tribler_gui/widgets/loadingpage.py +++ b/src/tribler-gui/tribler_gui/widgets/loadingpage.py @@ -2,6 +2,7 @@ from PyQt5.QtWidgets import QGraphicsScene, QWidget from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect, get_image_path @@ -28,6 +29,8 @@ class LoadingPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.loading_label = None self.upgrading = False diff --git a/src/tribler-gui/tribler_gui/widgets/searchresultswidget.py b/src/tribler-gui/tribler_gui/widgets/searchresultswidget.py index 6d335e5fa91..c36b65c87c4 100644 --- a/src/tribler-gui/tribler_gui/widgets/searchresultswidget.py +++ b/src/tribler-gui/tribler_gui/widgets/searchresultswidget.py @@ -9,6 +9,7 @@ from tribler_common.utilities import Query, to_fts_query from tribler_core.components.metadata_store.db.serialization import CHANNEL_TORRENT, COLLECTION_NODE, REGULAR_TORRENT +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect, get_ui_file_path, tr @@ -49,6 +50,8 @@ def complete(self): class SearchResultsWidget(AddBreadcrumbOnShowMixin, widget_form, widget_class): def __init__(self, parent=None): widget_class.__init__(self, parent=parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self._logger = logging.getLogger(self.__class__.__name__) try: diff --git a/src/tribler-gui/tribler_gui/widgets/settingspage.py b/src/tribler-gui/tribler_gui/widgets/settingspage.py index 05059aa9d5d..2482ecc92f2 100644 --- a/src/tribler-gui/tribler_gui/widgets/settingspage.py +++ b/src/tribler-gui/tribler_gui/widgets/settingspage.py @@ -20,6 +20,7 @@ PAGE_SETTINGS_SEEDING, ) from tribler_gui.dialogs.confirmationdialog import ConfirmationDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import ( AVAILABLE_TRANSLATIONS, @@ -42,6 +43,8 @@ class SettingsPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.settings = None self.version_history = None self.lang_list = sorted([lang_name for lang_name, lang_code in AVAILABLE_TRANSLATIONS.items()]) diff --git a/src/tribler-gui/tribler_gui/widgets/subscriptionswidget.py b/src/tribler-gui/tribler_gui/widgets/subscriptionswidget.py index 3a7273cbf85..321071770a5 100644 --- a/src/tribler-gui/tribler_gui/widgets/subscriptionswidget.py +++ b/src/tribler-gui/tribler_gui/widgets/subscriptionswidget.py @@ -3,6 +3,7 @@ from PyQt5.QtWidgets import QLabel, QWidget from tribler_common.sentry_reporter.sentry_mixin import AddBreadcrumbOnShowMixin +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect, format_votes_rich_text, get_votes_rating_description, tr from tribler_gui.widgets.tablecontentdelegate import DARWIN, WINDOWS @@ -15,6 +16,7 @@ class SubscriptionsWidget(AddBreadcrumbOnShowMixin, QWidget): def __init__(self, parent): QWidget.__init__(self, parent) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) self.subscribe_button = None self.initialized = False diff --git a/src/tribler-gui/tribler_gui/widgets/tabbuttonpanel.py b/src/tribler-gui/tribler_gui/widgets/tabbuttonpanel.py index b3b21711696..91ba3b8bdc5 100644 --- a/src/tribler-gui/tribler_gui/widgets/tabbuttonpanel.py +++ b/src/tribler-gui/tribler_gui/widgets/tabbuttonpanel.py @@ -1,7 +1,7 @@ from PyQt5.QtCore import pyqtSignal from PyQt5.QtWidgets import QWidget -from tribler_common.sentry_reporter.sentry_reporter import SentryReporter +from tribler_gui.error_handler import ErrorHandler from tribler_gui.utilities import connect @@ -23,7 +23,7 @@ def initialize(self): connect(button.clicked_tab_button, self.on_tab_button_click) def on_tab_button_click(self, clicked_button): - SentryReporter.add_breadcrumb(message=f'{clicked_button.objectName()}.Click', category='UI', level='info') + ErrorHandler.sentry_reporter.add_breadcrumb(message=f'{clicked_button.objectName()}.Click', category='UI', level='info') self.deselect_all_buttons(except_select=clicked_button) self.clicked_tab_button.emit(clicked_button.objectName()) diff --git a/src/tribler-gui/tribler_gui/widgets/trustgraphpage.py b/src/tribler-gui/tribler_gui/widgets/trustgraphpage.py index bbaeb42ed7d..3070d249070 100644 --- a/src/tribler-gui/tribler_gui/widgets/trustgraphpage.py +++ b/src/tribler-gui/tribler_gui/widgets/trustgraphpage.py @@ -21,6 +21,7 @@ TB, TRUST_GRAPH_PEER_LEGENDS, ) +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect, format_size, html_label, tr @@ -83,6 +84,7 @@ def mouseDragEvent(self, event): class TrustGraphPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) self.trust_graph = None self.graph_view = None diff --git a/src/tribler-gui/tribler_gui/widgets/trustpage.py b/src/tribler-gui/tribler_gui/widgets/trustpage.py index 54a6736e214..864e72c0b82 100644 --- a/src/tribler-gui/tribler_gui/widgets/trustpage.py +++ b/src/tribler-gui/tribler_gui/widgets/trustpage.py @@ -6,6 +6,7 @@ from tribler_gui.defs import PB, TB from tribler_gui.dialogs.trustexplanationdialog import TrustExplanationDialog +from tribler_gui.error_handler import ErrorHandler from tribler_gui.tribler_request_manager import TriblerNetworkRequest from tribler_gui.utilities import connect from tribler_gui.widgets.graphs.dataplot import TimeSeriesDataPlot @@ -28,6 +29,8 @@ class TrustPage(AddBreadcrumbOnShowMixin, QWidget): def __init__(self): QWidget.__init__(self) + self.set_sentry_reporter(ErrorHandler.sentry_reporter) + self.trust_plot = None self.history = None self.byte_scale = 1024 * 1024