Install Sentry error reporting system

This commit is contained in:
David Vierra 2017-06-27 12:25:03 -10:00
parent 1e2eda9c47
commit 4b86472577
5 changed files with 188 additions and 46 deletions

View File

@ -9,16 +9,22 @@ import platform
from PySide import QtGui, QtCore from PySide import QtGui, QtCore
from mcedit2.sentry import get_sentry_client
from mcedit2.ui.dialogs.error_dialog import Ui_errorDialog from mcedit2.ui.dialogs.error_dialog import Ui_errorDialog
from mcedit2.util import qglcontext from mcedit2.util import qglcontext
from mcedit2.util.resources import isSrcCheckout from mcedit2.util.resources import isSrcCheckout
from mcedit2.util.screen import centerWidgetInScreen from mcedit2.util.screen import centerWidgetInScreen
from mcedit2.util.settings import Settings
from mcedit2.util.showprogress import MCEProgressDialog from mcedit2.util.showprogress import MCEProgressDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
_errorShown = False _errorShown = False
settings = Settings()
ReportErrorSetting = settings.getOption("errors/reporting_enabled", bool, True)
def showErrorDialog(text, tb=None, fatal=True): def showErrorDialog(text, tb=None, fatal=True):
global _errorShown global _errorShown
@ -29,7 +35,6 @@ def showErrorDialog(text, tb=None, fatal=True):
if grabber: if grabber:
grabber.releaseMouse() grabber.releaseMouse()
dialog = ErrorDialog(text, tb, fatal) dialog = ErrorDialog(text, tb, fatal)
dialog.exec_() dialog.exec_()
_errorShown = False _errorShown = False
@ -80,18 +85,24 @@ class ErrorDialog(QtGui.QDialog, Ui_errorDialog):
self.quitMCEditButton.setVisible(fatal) self.quitMCEditButton.setVisible(fatal)
self.quitMCEditButton.clicked.connect(self.quitMCEdit) self.quitMCEditButton.clicked.connect(self.quitMCEdit)
self.continueButton.clicked.connect(self.continueMCEdit)
self.debugButton.setEnabled(isSrcCheckout()) self.debugButton.setEnabled(isSrcCheckout())
self.debugButton.clicked.connect(self.debugPdb) self.debugButton.clicked.connect(self.debugPdb)
self.reportErrorCheckbox.toggled.connect(self.reportErrorToggled)
self.reportErrorCheckbox.setChecked(ReportErrorSetting.value())
try: try:
import Pastebin import Pastebin
except ImportError: except ImportError:
self.copyToPastebinButton.setVisible(False) self.copyToPastebinButton.setVisible(False)
self.pastebinURLBox.setVisible(False)
else: else:
self.copyToPastebinButton.setVisible(True) self.copyToPastebinButton.setVisible(True)
self.copyToPastebinButton.clicked.connect(self.copyToPastebin) self.pastebinURLBox.setVisible(True)
self.pastebinURLBox.setVisible(False) self.copyToPastebinButton.clicked.connect(self.copyToPastebin)
def show(self, *args, **kwargs): def show(self, *args, **kwargs):
super(ErrorDialog, self).show(*args, **kwargs) super(ErrorDialog, self).show(*args, **kwargs)
@ -117,21 +128,42 @@ class ErrorDialog(QtGui.QDialog, Ui_errorDialog):
except Exception as e: except Exception as e:
log.warn("Failed to upload to pastebin!", exc_info=1) log.warn("Failed to upload to pastebin!", exc_info=1)
self.copyToPastebinLabel.setText(self.tr("Failed to upload to pastebin: ") + str(e)) self.copyToPastebinLabel.setText(self.tr("Failed to upload to pastebin: ") + str(e))
if e.message.startswith("https://pastebin.com"):
url = e.message
finally: finally:
dialog.hide() dialog.hide()
if url: if url:
self.pastebinURLBox.setVisible(True)
self.pastebinURLBox.setText(url) self.pastebinURLBox.setText(url)
QtGui.QApplication.clipboard().setText(url) QtGui.QApplication.clipboard().setText(url)
self.copyToPastebinLabel.setText(self.tr("Pastebin URL copied to clipboard!")) self.copyToPastebinLabel.setText(self.tr("Pastebin URL copied to clipboard!"))
def restartMCEdit(self): def restartMCEdit(self):
self.reportToSentry()
QtCore.QProcess.startDetached(sys.executable, sys.argv[1:]) QtCore.QProcess.startDetached(sys.executable, sys.argv[1:])
raise SystemExit raise SystemExit
def quitMCEdit(self): def quitMCEdit(self):
self.reportToSentry()
raise SystemExit raise SystemExit
def continueMCEdit(self):
self.reportToSentry()
self.accept()
def reportToSentry(self):
if not self.reportErrorCheckbox.isChecked():
return
client = get_sentry_client()
client.captureException(self.exc_info)
def reportErrorToggled(self, checked):
ReportErrorSetting.setValue(checked)
page = 0 if checked else 1
self.reportingLabelStack.setCurrentIndex(page)
def debugPdb(self): def debugPdb(self):
import pdb; pdb.post_mortem(self.exc_info[2]) import pdb; pdb.post_mortem(self.exc_info[2])

View File

@ -45,6 +45,9 @@ from mceditlib.anvil.adapter import SessionLockLost
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class UserRequestedError(ValueError):
""" Raised from the "Raise Error" item in the "Debug" menu. Used to test error reporting. """
class MCEditMainWindow(QtGui.QMainWindow, Ui_mainWindow): class MCEditMainWindow(QtGui.QMainWindow, Ui_mainWindow):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MCEditMainWindow, self).__init__(*args, **kwargs) super(MCEditMainWindow, self).__init__(*args, **kwargs)
@ -428,7 +431,7 @@ class MCEditApp(QtGui.QApplication):
self.tr("Raise an error? This may crash MCEdit."), self.tr("Raise an error? This may crash MCEdit."),
buttons=QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) buttons=QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if ret == QtGui.QMessageBox.Yes: if ret == QtGui.QMessageBox.Yes:
raise ValueError("User requested error") raise UserRequestedError("User requested error")
debugMenu.addAction(self.tr("Raise Error")).triggered.connect(raiseError) debugMenu.addAction(self.tr("Raise Error")).triggered.connect(raiseError)

View File

@ -12,6 +12,7 @@ import sys
import OpenGL import OpenGL
from mcedit2.sentry import get_sentry_client
from mcedit2.util import custom_traceback from mcedit2.util import custom_traceback
import codecs import codecs
@ -168,6 +169,7 @@ def startup():
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads, True) QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads, True)
global editorApp global editorApp
setup_logging() setup_logging()
get_sentry_client()
compile_ui() compile_ui()
sys.excepthook = excepthook sys.excepthook = excepthook

20
src/mcedit2/sentry.py Normal file
View File

@ -0,0 +1,20 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import logging
from raven import Client, breadcrumbs
_client = None
def get_sentry_client():
global _client
if _client is None:
from mcedit2 import __version__
_client = Client('https://76ebd10b53b841fe8ec9d928f12671e1:d33c89b4955c41338b0deb96dc7be78f@sentry.io/184596',
install_sys_hook=False,
release=__version__)
breadcrumbs.register_logging_handler(_log_handler)
return _client
def _log_handler(logger, level, *a):
return level <= logging.DEBUG

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>690</width> <width>726</width>
<height>550</height> <height>619</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -18,8 +18,13 @@
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;An Error Has Occurred:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>An Error Has Occurred:</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::RichText</enum> <enum>Qt::RichText</enum>
@ -37,6 +42,11 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>(no error yet!)</string> <string>(no error yet!)</string>
</property> </property>
@ -62,15 +72,88 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QTextBrowser" name="tracebackView"/> <widget class="QTextBrowser" name="tracebackView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="reportErrorCheckbox">
<property name="text">
<string>Report Error</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="reportingLabelStack">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="autoSendErrorLabel">
<property name="text">
<string>This error will be automatically reported when this window is closed.</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="manualSendErrorLabel">
<property name="text"> <property name="text">
<string>Send this error report to the plugin or application developer to help get it fixed. </string> <string>Send this error report to the plugin or application developer to help get it fixed. </string>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QLabel" name="copyToPastebinLabel"> <widget class="QLabel" name="copyToPastebinLabel">
<property name="text"> <property name="text">
@ -78,13 +161,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="copyToPastebinButton">
<property name="text">
<string>Copy to PasteBin</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLineEdit" name="pastebinURLBox"> <widget class="QLineEdit" name="pastebinURLBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -107,13 +207,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="copyToPastebinButton">
<property name="text">
<string>Copy to PasteBin</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="restartMCEditButton"> <widget class="QPushButton" name="restartMCEditButton">
<property name="text"> <property name="text">
@ -141,24 +234,16 @@
</layout> </layout>
</item> </item>
</layout> </layout>
<zorder>restartMCEditLabel</zorder>
<zorder>label_3</zorder>
<zorder>tracebackView</zorder>
<zorder>copyToPastebinLabel</zorder>
<zorder>pastebinURLBox</zorder>
<zorder>copyToPastebinButton</zorder>
<zorder>reportingLabelStack</zorder>
<zorder>reportErrorCheckbox</zorder>
<zorder>autoSendErrorLabel</zorder>
</widget> </widget>
<resources/> <resources/>
<connections> <connections/>
<connection>
<sender>continueButton</sender>
<signal>clicked()</signal>
<receiver>errorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>650</x>
<y>523</y>
</hint>
<hint type="destinationlabel">
<x>505</x>
<y>5</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>