diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py index 7f92d38e..6cb32478 100644 --- a/gns3server/crash_report.py +++ b/gns3server/crash_report.py @@ -17,7 +17,7 @@ try: import sentry_sdk - from sentry_sdk.integrations.aiohttp import AioHttpIntegration + from sentry_sdk.integrations.logging import LoggingIntegration SENTRY_SDK_AVAILABLE = True except ImportError: # Sentry SDK is not installed with deb package in order to simplify packaging @@ -42,7 +42,8 @@ log = logging.getLogger(__name__) if __version_info__[3] != 0: import faulthandler - # Display a traceback in case of segfault crash. Usefull when frozen + # Display a traceback in case of segfault crash. + # Useful when this application is frozen. # Not enabled by default for security reason log.info("Enable catching segfault") try: @@ -78,10 +79,13 @@ class CrashReport: else: log.error("The SSL certificate bundle file '{}' could not be found".format(cacert_resource)) + # Don't send log records as events. + sentry_logging = LoggingIntegration(level=logging.INFO, event_level=None) + sentry_sdk.init(dsn=CrashReport.DSN, release=__version__, ca_certs=cacert, - integrations=[AioHttpIntegration()]) + integrations=[sentry_logging]) tags = { "os:name": platform.system(), @@ -128,20 +132,39 @@ class CrashReport: for key, value in extra_context.items(): scope.set_extra(key, value) - def capture_exception(self): + def capture_exception(self, request): + if not SENTRY_SDK_AVAILABLE: return - if os.path.exists(".git"): + + if not hasattr(sys, "frozen") and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".git")): log.warning(".git directory detected, crash reporting is turned off for developers.") return + server_config = Config.instance().get_section_config("Server") if server_config.getboolean("report_errors"): + if not SENTRY_SDK_AVAILABLE: + log.warning("Cannot capture exception: Sentry SDK is not available") + return + + if os.path.exists(".git"): + log.warning(".git directory detected, crash reporting is turned off for developers.") + return + try: - sentry_sdk.capture_exception() + if request: + # add specific extra request information + with sentry_sdk.push_scope() as scope: + scope.set_extra("method", request.method) + scope.set_extra("url", request.path) + scope.set_extra("json", request.json) + sentry_sdk.capture_exception() + else: + sentry_sdk.capture_exception() log.info("Crash report sent with event ID: {}".format(sentry_sdk.last_event_id())) except Exception as e: - log.error("Can't send crash report to Sentry: {}".format(e)) + log.warning("Can't send crash report to Sentry: {}".format(e)) @classmethod def instance(cls): diff --git a/gns3server/version.py b/gns3server/version.py index 4ce714e9..745edcdc 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,7 +23,7 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "2.2.9dev1" +__version__ = "2.2.9dev2" __version_info__ = (2, 2, 9, 99) if "dev" in __version__: diff --git a/gns3server/web/route.py b/gns3server/web/route.py index c70dbbc3..d1275250 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -242,7 +242,7 @@ class Route(object): log.error("Uncaught exception detected: {type}".format(type=type(e)), exc_info=1) response = Response(request=request, route=route) response.set_status(500) - CrashReport.instance().capture_exception() + CrashReport.instance().capture_exception(request) exc_type, exc_value, exc_tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_tb) if api_version is not None: diff --git a/requirements.txt b/requirements.txt index ef8f0f4c..10577889 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,6 @@ jsonschema==2.6.0; python_version < '3.8' # pyup: ignore aiohttp==3.6.2 aiohttp-cors==0.7.0 aiofiles==0.4.0 -aiocontextvars==0.2.2; python_version < '3.7' Jinja2>=2.7.3 sentry-sdk>=0.14.4 psutil==5.6.6