diff options
Diffstat (limited to 'cura/CrashHandler.py')
-rw-r--r-- | cura/CrashHandler.py | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index e72180887c..db44daa77c 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -10,7 +10,7 @@ import os.path import uuid import json import locale -from typing import cast +from typing import cast, Any try: from sentry_sdk.hub import Hub @@ -32,6 +32,8 @@ from UM.Resources import Resources from cura import ApplicationMetadata catalog = i18nCatalog("cura") +home_dir = os.path.expanduser("~") + MYPY = False if MYPY: @@ -83,6 +85,21 @@ class CrashHandler: self.dialog = QDialog() self._createDialog() + @staticmethod + def pruneSensitiveData(obj: Any) -> Any: + if isinstance(obj, str): + return obj.replace("\\\\", "\\").replace(home_dir, "<user_home>") + if isinstance(obj, list): + return [CrashHandler.pruneSensitiveData(item) for item in obj] + if isinstance(obj, dict): + return {k: CrashHandler.pruneSensitiveData(v) for k, v in obj.items()} + + return obj + + @staticmethod + def sentryBeforeSend(event, hint): + return CrashHandler.pruneSensitiveData(event) + def _createEarlyCrashDialog(self): dialog = QDialog() dialog.setMinimumWidth(500) @@ -133,8 +150,9 @@ class CrashHandler: self._sendCrashReport() os._exit(1) - ## Backup the current resource directories and create clean ones. def _backupAndStartClean(self): + """Backup the current resource directories and create clean ones.""" + Resources.factoryReset() self.early_crash_dialog.close() @@ -145,8 +163,9 @@ class CrashHandler: def _showDetailedReport(self): self.dialog.exec_() - ## Creates a modal dialog. def _createDialog(self): + """Creates a modal dialog.""" + self.dialog.setMinimumWidth(640) self.dialog.setMinimumHeight(640) self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report")) @@ -161,7 +180,6 @@ class CrashHandler: layout.addWidget(self._informationWidget()) layout.addWidget(self._exceptionInfoWidget()) layout.addWidget(self._logInfoWidget()) - layout.addWidget(self._userDescriptionWidget()) layout.addWidget(self._buttonsWidget()) def _close(self): @@ -197,6 +215,16 @@ class CrashHandler: locale.getdefaultlocale()[0] self.data["locale_cura"] = self.cura_locale + try: + from cura.CuraApplication import CuraApplication + plugins = CuraApplication.getInstance().getPluginRegistry() + self.data["plugins"] = { + plugin_id: plugins.getMetaData(plugin_id)["plugin"]["version"] + for plugin_id in plugins.getInstalledPlugins() if not plugins.isBundledPlugin(plugin_id) + } + except: + self.data["plugins"] = {"[FAILED]": "0.0.0"} + crash_info = "<b>" + catalog.i18nc("@label Cura version number", "Cura version") + ":</b> " + str(self.cura_version) + "<br/>" crash_info += "<b>" + catalog.i18nc("@label", "Cura language") + ":</b> " + str(self.cura_locale) + "<br/>" crash_info += "<b>" + catalog.i18nc("@label", "OS language") + ":</b> " + str(self.data["locale_os"]) + "<br/>" @@ -219,8 +247,13 @@ class CrashHandler: scope.set_tag("locale_os", self.data["locale_os"]) scope.set_tag("locale_cura", self.cura_locale) scope.set_tag("is_enterprise", ApplicationMetadata.IsEnterpriseVersion) - - scope.set_user({"id": str(uuid.getnode())}) + + scope.set_context("plugins", self.data["plugins"]) + + user_id = uuid.getnode() # On all of Cura's supported platforms, this returns the MAC address which is pseudonymical information (!= anonymous). + user_id %= 2 ** 16 # So to make it anonymous, apply a bitmask selecting only the last 16 bits. + # This prevents it from being traceable to a specific user but still gives somewhat of an idea of whether it's just the same user hitting the same crash over and over again, or if it's widespread. + scope.set_user({"id": str(user_id)}) return group @@ -374,21 +407,6 @@ class CrashHandler: return group - def _userDescriptionWidget(self): - group = QGroupBox() - group.setTitle(catalog.i18nc("@title:groupbox", "User description" + - " (Note: Developers may not speak your language, please use English if possible)")) - layout = QVBoxLayout() - - # When sending the report, the user comments will be collected - self.user_description_text_area = QTextEdit() - self.user_description_text_area.setFocus(True) - - layout.addWidget(self.user_description_text_area) - group.setLayout(layout) - - return group - def _buttonsWidget(self): buttons = QDialogButtonBox() buttons.addButton(QDialogButtonBox.Close) @@ -403,9 +421,6 @@ class CrashHandler: return buttons def _sendCrashReport(self): - # Before sending data, the user comments are stored - self.data["user_info"] = self.user_description_text_area.toPlainText() - if with_sentry_sdk: try: hub = Hub.current |