def tes_macos_package_in_app_detection(self): data = { "platform": "cocoa", "debug_meta": {"images": []}, # omitted "exception": { "values": [ { "stacktrace": { "frames": [ { "function": "-[CRLCrashAsyncSafeThread crash]", "package": "/Users/haza/Library/Developer/Xcode/Archives/2017-06-19/CrashProbe 19-06-2017, 08.53.xcarchive/Products/Applications/CrashProbe.app/Contents/Frameworks/CrashLib.framework/Versions/A/CrashLib", "instruction_addr": 4295098388, }, { "function": "[KSCrash ]", "package": "/usr/lib/system/libdyld.dylib", "instruction_addr": 4295098388, }, ] }, "type": "NSRangeException", } ] }, "contexts": {"os": {"version": "10.12.5", "type": "os", "name": "macOS"}}, } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) frames = data["exception"]["values"][0]["stacktrace"]["frames"] assert frames[0]["in_app"] is True assert frames[1]["in_app"] is False
def test_ios_package_in_app_detection(self): data = { "platform": "native", "stacktrace": { "frames": [ { "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": "0x1000", }, { "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/foo.dylib", "instruction_addr": "0x2000", }, { "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/libswiftCore.dylib", "instruction_addr": "0x3000", }, {"package": "/usr/lib/whatever.dylib", "instruction_addr": "0x4000"}, ] }, } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) # App object should be in_app assert data["stacktrace"]["frames"][0]["in_app"] is True # Framework should be in app (but optional) assert data["stacktrace"]["frames"][1]["in_app"] is True # libswift should not be system assert data["stacktrace"]["frames"][2]["in_app"] is False # Unknown object should default to not in_app assert data["stacktrace"]["frames"][3]["in_app"] is False
def create_event(data, group_id=123): mgr = EventManager(data=data, grouping_config=get_default_grouping_config_dict()) mgr.normalize() data = mgr.get_data() evt = eventstore.create_event(data=data) evt.project = project = Project(id=123) evt.group = Group(id=group_id, project=project) return evt
def test_similarity_extract_fingerprinting(fingerprint_input, insta_snapshot): similarity = sentry.similarity.features2 _, evt = fingerprint_input.create_event(get_default_grouping_config_dict()) evt.project = project = Project(id=123) evt.group = Group(id=123, project=project) snapshot = [] for label, features in similarity.extract(evt).items(): for feature in features: snapshot.append("{}: {}".format(":".join(label), json.dumps(feature, sort_keys=True))) insta_snapshot("\n".join(sorted(snapshot)))
def test_event_hash_variant(insta_snapshot, config_name, test_name, log): with open(os.path.join(_fixture_path, test_name + ".json")) as f: input = json.load(f) # Customize grouping config from the _grouping config grouping_config = get_default_grouping_config_dict(config_name) grouping_info = input.pop("_grouping", None) or {} enhancement_base = grouping_info.get("enhancement_base") enhancements = grouping_info.get("enhancements") if enhancement_base or enhancements: enhancement_bases = [enhancement_base] if enhancement_base else [] e = Enhancements.from_config_string(enhancements or "", bases=enhancement_bases) grouping_config["enhancements"] = e.dumps() # Normalize the event mgr = EventManager(data=input, grouping_config=grouping_config) mgr.normalize() data = mgr.get_data() # Normalize the stacktrace for grouping. This normally happens in # save() normalize_stacktraces_for_grouping(data, load_grouping_config(grouping_config)) evt = eventstore.create_event(data=data) # Make sure we don't need to touch the DB here because this would # break stuff later on. evt.project = None rv = [] for (key, value) in sorted(evt.get_grouping_variants().items()): if rv: rv.append("-" * 74) rv.append("%s:" % key) dump_variant(value, rv, 1) output = "\n".join(rv) log(repr(evt.get_hashes())) assert evt.get_grouping_config() == grouping_config insta_snapshot(output)
def ios_function_name_in_app_detection(self, function, isInApp: bool): data = { "platform": "cocoa", "debug_meta": { "images": [] }, # omitted "exception": { "values": [{ "stacktrace": { "frames": [ { "function": function, "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, # We need two frames otherwise all frames are inApp { "function": "[KSCrash ]", "package": "/usr/lib/system/libdyld.dylib", "instruction_addr": 4295098388, }, ] }, "type": "NSRangeException", }] }, "contexts": { "os": { "version": "9.3.2", "type": "os", "name": "iOS" } }, } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) frames = data["exception"]["values"][0]["stacktrace"]["frames"] assert frames[0]["in_app"] is isInApp, ("For function: " + function + " expected:" + str(isInApp))
def tes_macos_package_in_app_detection(self): data = { "platform": "cocoa", "debug_meta": { "images": [] # omitted }, "exception": { "values": [ { "stacktrace": { "frames": [ { "function": "-[CRLCrashAsyncSafeThread crash]", "package": "/Users/haza/Library/Developer/Xcode/Archives/2017-06-19/CrashProbe 19-06-2017, 08.53.xcarchive/Products/Applications/CrashProbe.app/Contents/Frameworks/CrashLib.framework/Versions/A/CrashLib", "instruction_addr": 4295098388 }, { "function": "[KSCrash ]", "package": "/usr/lib/system/libdyld.dylib", "instruction_addr": 4295098388, }, ] }, "type": "NSRangeException", } ] }, "contexts": { "os": { "version": "10.12.5", "type": "os", "name": "macOS" } }, } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) frames = data['exception']['values'][0]['stacktrace']['frames'] assert frames[0]['in_app'] is True assert frames[1]['in_app'] is False
def test_event_hash_variant(config_name, grouping_input, insta_snapshot, log): grouping_config = get_default_grouping_config_dict(config_name) evt = grouping_input.create_event(grouping_config) # Make sure we don't need to touch the DB here because this would # break stuff later on. evt.project = None rv = [] for (key, value) in sorted(evt.get_grouping_variants().items()): if rv: rv.append("-" * 74) rv.append("%s:" % key) dump_variant(value, rv, 1) output = "\n".join(rv) log(repr(evt.get_hashes())) assert evt.get_grouping_config() == grouping_config insta_snapshot(output)
def test_ios_package_in_app_detection(self): data = { 'platform': 'native', 'stacktrace': { 'frames': [ { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest', 'instruction_addr': '0x1000' }, { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/foo.dylib', 'instruction_addr': '0x2000' }, { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/libswiftCore.dylib', 'instruction_addr': '0x3000' }, { 'package': '/usr/lib/whatever.dylib', 'instruction_addr': '0x4000' }, ] } } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) # App object should be in_app assert data['stacktrace']['frames'][0]['in_app'] is True # Framework should be in app (but optional) assert data['stacktrace']['frames'][1]['in_app'] is True # libswift should not be system assert data['stacktrace']['frames'][2]['in_app'] is False # Unknown object should default to not in_app assert data['stacktrace']['frames'][3]['in_app'] is False
def test_ios_package_in_app_detection(self): data = { 'platform': 'native', 'stacktrace': { 'frames': [ { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest', 'instruction_addr': '0x1000' }, { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/foo.dylib', 'instruction_addr': '0x2000' }, { 'package': '/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/Frameworks/libswiftCore.dylib', 'instruction_addr': '0x3000' }, { 'package': '/usr/lib/whatever.dylib', 'instruction_addr': '0x4000' }, ] } } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) # App object should be in_app assert data['stacktrace']['frames'][0]['in_app'] is True # Framework should be in app (but optional) assert data['stacktrace']['frames'][1]['in_app'] is True # libswift should not be system assert data['stacktrace']['frames'][2]['in_app'] is False # Unknown object should default to not in_app assert data['stacktrace']['frames'][3]['in_app'] is False
def test_ios_function_name_in_app_detection(self): data = { "platform": "cocoa", "debug_meta": {"images": []}, # omitted "exception": { "values": [ { "stacktrace": { "frames": [ { "function": "+[RNSentry ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[SentryClient ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "kscrash_foobar", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "kscm_foobar", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrash ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrash]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrashy]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, ] }, "type": "NSRangeException", } ] }, "contexts": {"os": {"version": "9.3.2", "type": "os", "name": "iOS"}}, } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) frames = data["exception"]["values"][0]["stacktrace"]["frames"] assert frames[0]["in_app"] is False assert frames[1]["in_app"] is False assert frames[2]["in_app"] is False assert frames[3]["in_app"] is False assert frames[4]["in_app"] is False assert frames[5]["in_app"] is True assert frames[6]["in_app"] is True
import pytest from sentry.grouping.api import get_default_grouping_config_dict from sentry.grouping.strategies.configurations import CONFIGURATIONS from tests.sentry.grouping import grouping_input as grouping_inputs CONFIGS = { key: get_default_grouping_config_dict(key) for key in sorted(CONFIGURATIONS.keys()) } def benchmark_available(): try: import pytest_benchmark # NOQA except ModuleNotFoundError: return False else: return True @pytest.mark.skipif(not benchmark_available(), reason="requires pytest-benchmark") @pytest.mark.parametrize("config_name", sorted(CONFIGURATIONS.keys()), ids=lambda x: x.replace("-", "_")) def test_benchmark_grouping(config_name, benchmark): config = CONFIGS[config_name] input_iter = iter(grouping_inputs) def setup():
"").lower().split(",") if x ] class CategorizationInput: def __init__(self, filename): self.filename = filename @cached_property def data(self): with open(os.path.join(_fixture_path, self.filename)) as f: return _pre_scrub_event(json.load(f)) CONFIG = load_grouping_config( get_default_grouping_config_dict("mobile:2021-02-12")) def get_stacktrace_render(data): """ Platform agnostic stacktrace renderer with annotations """ rv = [] for exc in get_path(data, "exception", "values", filter=True) or (): ty = get_path(exc, "type") or "_" value = get_path(exc, "value") or "_" thread_id = get_path(exc, "id") or "_" crashed = get_path(exc, "crashed", default="_") rv.append("") rv.append("") rv.append(f"{ty}:{value} (thread_id:{thread_id}, crashed:{crashed})")
import pytest from sentry.grouping.fingerprinting import FingerprintingRules, InvalidFingerprintingConfig from sentry.grouping.api import get_default_grouping_config_dict from tests.sentry.grouping import with_fingerprint_input GROUPING_CONFIG = get_default_grouping_config_dict() def test_basic_parsing(insta_snapshot): rules = FingerprintingRules.from_config_string( """ # This is a config type:DatabaseUnavailable -> DatabaseUnavailable function:assertion_failed module:foo -> AssertionFailed, foo app:true -> aha app:true -> {{ default }} !path:**/foo/** -> everything !"path":**/foo/** -> everything logger:sentry.* -> logger-, {{ logger }} message:"\\x\\xff" -> stuff logger:sentry.* -> logger-{{ logger }}, title="Message from {{ logger }}" logger:sentry.* -> logger-{{ logger }} title="Message from {{ logger }}" """ ) assert rules._to_config_structure() == { "rules": [ { "matchers": [["type", "DatabaseUnavailable"]], "fingerprint": ["DatabaseUnavailable"],
_SHOULD_DELETE_DATA = os.environ.get("SENTRY_TEST_GROUPING_DELETE_USELESS_DATA") == "1" _DELETE_KEYWORDS = os.environ.get("SENTRY_TEST_GROUPING_DELETE_KEYWORDS", "").lower().split(",") class CategorizationInput: def __init__(self, filename): self.filename = filename @cached_property def data(self): with open(os.path.join(_fixture_path, self.filename)) as f: return _pre_scrub_event(json.load(f)) CONFIG = load_grouping_config(get_default_grouping_config_dict("mobile:2021-02-12")) def get_stacktrace_render(data): """ Platform agnostic stacktrace renderer with annotations """ rv = [] for exc in get_path(data, "exception", "values", filter=True) or (): ty = get_path(exc, "type") or "_" value = get_path(exc, "value") or "_" thread_id = get_path(exc, "id") or "_" crashed = get_path(exc, "crashed", default="_") rv.append("") rv.append("") rv.append(f"{ty}:{value} (thread_id:{thread_id}, crashed:{crashed})")
def test_ios_function_name_in_app_detection(self): data = { "platform": "cocoa", "debug_meta": { "images": [] # omitted }, "exception": { "values": [ { "stacktrace": { "frames": [ { "function": "+[RNSentry ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[SentryClient ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "kscrash_foobar", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "kscm_foobar", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrash ]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrash]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, { "function": "+[KSCrashy]", "package": "/var/containers/Bundle/Application/B33C37A8-F933-4B6B-9FFA-152282BFDF13/SentryTest.app/SentryTest", "instruction_addr": 4295098388, }, ] }, "type": "NSRangeException", } ] }, "contexts": { "os": { "version": "9.3.2", "type": "os", "name": "iOS" } } } config = load_grouping_config(get_default_grouping_config_dict()) normalize_stacktraces_for_grouping(data, grouping_config=config) frames = data['exception']['values'][0]['stacktrace']['frames'] assert frames[0]['in_app'] is False assert frames[1]['in_app'] is False assert frames[2]['in_app'] is False assert frames[3]['in_app'] is False assert frames[4]['in_app'] is False assert frames[5]['in_app'] is True assert frames[6]['in_app'] is True