Repository: getsentry/sentry

Issue:
Support release field for customized fingerprint rules
### Problem Statement

## Context
Sentry's App Hangs collected for iOS Widgets extensions do not accurately reflect whether the extension code is hanging.

## Problem
I have disabled app hang collection in widgets in new clients, but old clients will continue to log them, and, under some circumstances, new clients may log some too.

App Hangs from widgets may be in their own group or share a group with real app hangs reflected in the main application or other app extensions, they just seem to happen a lot more in the cases they share a group with the main app or extensions.

I want to entirely stop collecting these app hangs for old clients, so it does not disrupt my team's ability to triage and resolve real app hangs.  If I cannot do this, my team is likely to have app hangs re-open as regressed even though they are not, and there's also likely to be a lot of noise both on alerts and also when browsing app hangs.  It will be very difficult to understand what's real and what isn't, as well as whether the issue is actually impacting users and at what level.

## My Solution
I went to Fingerprint Rules with the intent to group together all the app hangs coming from widgets releases so that they could be discarded and deleted.

Here's the fingerprint rule I tried:
```
tags.mechanism:"AppHang" tags.release:"com.getdropbox.Dropbox.Widgets*" -> widget_app_hangs title="Widget App Hang"
```

But it does not seem that `tags.release` exists?  The rule seems to do nothing.

### Solution Brainstorm

My intended solution would work, I think, if I could access release in some way inside a fingerprint rule.

I'm super open to other solutions for my problem.

Something else I tried that doesn't work entirely:
I can use inbound filters to drop all things from widgets, but the issue is that I still want things from widgets, I just don't want app hangs from widgets.  So that does not help solve the whole issue, only most of it.  I can drop those older versions entirely, at the expense of losing all their error reports, but some newer versions will have a (bad) cached value for the feature gate used to control whether we collect app hangs on widgets, that may live for a very long time.

### Product Area

Ingestion and Filtering

┆Issue is synchronized with this [Jira Improvement](https://getsentry.atlassian.net/browse/FEEDBACK-2132) by [Unito](https://www.unito.io)



Discussion:
Assigning to @getsentry/support for [routing](https://open.sentry.io/triage/#2-route) ⏲️
Tested this independently and confirming described behavior with `tags.release`.
Matching semver without package name doesn't work either.
`release` is not allowed by validation 
<img width="153" alt="Screenshot 2024-03-27 at 5 12 24 PM" src="https://github.com/getsentry/sentry/assets/490201/93b25e07-c3d6-4abd-9b3f-700ef41b7e9e">

Routing to @getsentry/product-owners-issues for [triage](https://develop.sentry.dev/processing-tickets/#3-triage) ⏲️
Hi @jboulter11 
I tend to use Discover to help me create fingerprint rules.

You should be using this:
`error.mechanism:AppHang  release:com.getdropbox.Dropbox.Widgets*`

The mechanism is part of the `error` field rather than a tag. Also the `release` is a field rather than a tag.

Please let me know if this works for you.
Unfortunately that does not work:
![Screenshot by Dropbox Capture](https://github.com/getsentry/sentry/assets/6633472/2a5456e6-5ddb-4234-88be-d06a829f7ab7)

I also used discover to help write this. :'( 
huh! Let me fix that.

Resolving patch:
diff --git a/src/sentry/grouping/fingerprinting/__init__.py b/src/sentry/grouping/fingerprinting/__init__.py
--- a/src/sentry/grouping/fingerprinting/__init__.py
+++ b/src/sentry/grouping/fingerprinting/__init__.py
@@ -283,6 +283,7 @@ def _from_config_structure(cls, data, bases=None):
     "family": "family",
     "app": "app",
     "sdk": "sdk",
+    "release": "release",
 }
 
 


Test patch:
diff --git a/tests/sentry/grouping/test_fingerprinting.py b/tests/sentry/grouping/test_fingerprinting.py
--- a/tests/sentry/grouping/test_fingerprinting.py
+++ b/tests/sentry/grouping/test_fingerprinting.py
@@ -130,6 +130,7 @@ def test_discover_field_parsing(insta_snapshot):
 stack.function:assertion_failed stack.module:foo      -> AssertionFailed, foo
 app:true                                        -> aha
 app:true                                        -> {{ default }}
+release:foo                                     -> {{ default }}
 """
     )
     assert rules._to_config_structure() == {
@@ -146,6 +147,7 @@ def test_discover_field_parsing(insta_snapshot):
             },
             {"matchers": [["app", "true"]], "fingerprint": ["aha"], "attributes": {}},
             {"matchers": [["app", "true"]], "fingerprint": ["{{ default }}"], "attributes": {}},
+            {"matchers": [["release", "foo"]], "fingerprint": ["{{ default }}"], "attributes": {}},
         ],
         "version": 1,
     }