From 2646aa4245f4b1cba59ac582b928df3989540b68 Mon Sep 17 00:00:00 2001 From: Mitchell Hentges Date: Tue, 12 May 2020 21:11:41 +0000 Subject: [PATCH] Bug 1636251: report |./mach| errors with Sentry r=rstewart These errors are reported to the "mach" project here: https://sentry.prod.mozaws.net/operations/mach/ Should only report exceptions caused by a failure in `mach` or its subcommands. Build/test/etc failures should not be sent to Sentry. Differential Revision: https://phabricator.services.mozilla.com/D74738 --- python/mach/mach/main.py | 4 +++ python/mach/mach/sentry.py | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 python/mach/mach/sentry.py diff --git a/python/mach/mach/main.py b/python/mach/mach/main.py index 319b5117ac12..eb217c2db01b 100644 --- a/python/mach/mach/main.py +++ b/python/mach/mach/main.py @@ -18,6 +18,7 @@ import traceback import uuid from collections import Iterable +from mach.sentry import register_sentry, report_exception from six import string_types from .base import ( @@ -319,6 +320,7 @@ To see more help for a specific command, run: Returns the integer exit code that should be used. 0 means success. All other values indicate failure. """ + register_sentry() # If no encoding is defined, we default to UTF-8 because without this # Python 2.7 will assume the default encoding of ASCII. This will blow @@ -375,6 +377,7 @@ To see more help for a specific command, run: stack = traceback.extract_tb(exc_tb) self._print_exception(sys.stdout, exc_type, exc_value, stack) + report_exception(exc_value) return 1 @@ -480,6 +483,7 @@ To see more help for a specific command, run: return e.exit_code except Exception: exc_type, exc_value, exc_tb = sys.exc_info() + report_exception(exc_value) # The first two frames are us and are never used. stack = traceback.extract_tb(exc_tb)[2:] diff --git a/python/mach/mach/sentry.py b/python/mach/mach/sentry.py new file mode 100644 index 000000000000..f7a9d10b98ae --- /dev/null +++ b/python/mach/mach/sentry.py @@ -0,0 +1,59 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import absolute_import + +import os +import re + +import sentry_sdk +from six.moves.configparser import SafeConfigParser, NoOptionError + +from mozboot.util import get_state_dir + + +# https://sentry.prod.mozaws.net/operations/mach/ +_SENTRY_DSN = "https://8228c9aff64949c2ba4a2154dc515f55@sentry.prod.mozaws.net/525" + + +def register_sentry(): + cfg_file = os.path.join(get_state_dir(), 'machrc') + config = SafeConfigParser() + + if not config.read(cfg_file): + return + + try: + telemetry_enabled = config.getboolean("build", "telemetry") + except NoOptionError: + return + + if not telemetry_enabled: + return + + sentry_sdk.init(_SENTRY_DSN, before_send=_settle_mach_module_id) + + +def _settle_mach_module_id(sentry_event, exception): + # Sentry groups issues according to the stack frames and their associated + # "module" properties. However, one of the modules is being reported + # like "mach.commands.26a828ef5164403eaff4305ab4cb0fab" (with a generated id). + # This function replaces that generated id with the static string "" + # so that grouping behaves as expected + + stacktrace_frames = sentry_event["exception"]["values"][0]["stacktrace"]["frames"] + for frame in stacktrace_frames: + module = frame.get("module") + if not module: + continue + + module = re.sub("mach\\.commands\\.[a-f0-9]{32}", "mach.commands.", + module) + frame["module"] = module + return sentry_event + + +def report_exception(exception): + # sentry_sdk won't report the exception if `sentry-sdk.init(...)` hasn't been called + sentry_sdk.capture_exception(exception)