Repository: getsentry/sentry

Issue:
 Inability to Search and Display Performance Custom Performance Measurements with Numbers
### Environment

SaaS (https://sentry.io/)

### Steps to Reproduce

Currently, I have set several measurements using the transaction.setMeasurement() method, which includes numeric values. For example:

```
transaction1.setMeasurement('frame.rate.avg', 50);
transaction1.setMeasurement('frame.rate.p50', 60);
transaction1.setMeasurement('frame.rate.a50', 70);
transaction1.setMeasurement('frame.rate.50', 80);
transaction1.setMeasurement('frame.rate.p1234', 10);
transaction1.setMeasurement('frame.rate.sdbibdijd', 20);
```

It show up in Sentry: 

![Screenshot 2023-07-12 at 5 26 35 PM](https://github.com/getsentry/sentry/assets/89524511/d28f1064-b596-415d-954c-b4bb4671cae7)

However, when attempting to search for these metrics in both the Discover and Dashboards features, it seems that only metrics without numbers are searchable. 

![Screenshot 2023-07-11 at 3 05 51 PM](https://github.com/getsentry/sentry/assets/89524511/cb18b0d9-a14e-4f06-854d-b2de5dc5449c)
![Screenshot 2023-07-12 at 5 28 10 PM](https://github.com/getsentry/sentry/assets/89524511/346a1ba3-e499-494f-a487-f17a72b3823b)

Additionally, these metrics are not available in the Discover columns unless the URL is manually edited to include them.
![Screenshot 2023-07-12 at 5 28 10 PM](https://github.com/getsentry/sentry/assets/89524511/27b9613f-adbd-47da-8e4f-9817d54e4440)


In summary: 
- Set measurements using the transaction.setMeasurement() method with numeric values.
- Attempt to search for these metrics using the Discover or Dashboards features.
- Observe that the metrics with numbers are not searchable and not available in the Discover columns by default.

### Expected Result

Metrics with numbers set using the transaction.setMeasurement() method should be searchable and visible in the Discover and Dashboards features without the need for manual URL modification.

### Actual Result

Metrics with numbers in their names are not searchable in both the Discover and Dashboards features. Additionally, these metrics are not available in the Discover columns. 

### Product Area

Dashboards

### Link

_No response_

### DSN

_No response_

### Version

_No response_


Discussion:
Assigning to @getsentry/support for [routing](https://open.sentry.io/triage/#2-route) ⏲️
Routing to @getsentry/product-owners-dashboards for [triage](https://develop.sentry.dev/processing-tickets/#3-triage) ⏲️
Is there any solutions ?? this is exactly my problems.
Any update about this? In my case `a.b` is showing up while `a.b.c` does not. Not sure if the amount of dots has anything to do with this issue.
Hey sorry this one fell off our Radar, I'm going to start some investigation into this and will have an update soon

Resolving patch:
diff --git a/src/sentry/snuba/metrics/naming_layer/mri.py b/src/sentry/snuba/metrics/naming_layer/mri.py
--- a/src/sentry/snuba/metrics/naming_layer/mri.py
+++ b/src/sentry/snuba/metrics/naming_layer/mri.py
@@ -49,9 +49,9 @@
 
 NAMESPACE_REGEX = r"(transactions|errors|issues|sessions|alerts|custom|spans|escalating_issues)"
 ENTITY_TYPE_REGEX = r"(c|s|d|g|e)"
-# This regex allows for a string of words composed of small letters alphabet characters with
+# This regex allows for a string of words composed of small letters alphanumeric characters with
 # allowed the underscore character, optionally separated by a single dot
-MRI_NAME_REGEX = r"([a-z_]+(?:\.[a-z_]+)*)"
+MRI_NAME_REGEX = r"([a-z0-9_]+(?:\.[a-z0-9_]+)*)"
 # ToDo(ahmed): Add a better regex for unit portion for MRI
 MRI_SCHEMA_REGEX_STRING = rf"(?P<entity>{ENTITY_TYPE_REGEX}):(?P<namespace>{NAMESPACE_REGEX})/(?P<name>{MRI_NAME_REGEX})@(?P<unit>[\w.]*)"
 MRI_SCHEMA_REGEX = re.compile(rf"^{MRI_SCHEMA_REGEX_STRING}$")


Test patch:
diff --git a/tests/sentry/snuba/metrics/test_naming_layer.py b/tests/sentry/snuba/metrics/test_naming_layer.py
--- a/tests/sentry/snuba/metrics/test_naming_layer.py
+++ b/tests/sentry/snuba/metrics/test_naming_layer.py
@@ -83,7 +83,6 @@ def test_valid_mri_schema_regex(name):
         "e:sessions/healthy..crashed.crashed@",
         "t:sessions/error.preaggr@none",
         "e:foo/error.preaggr@none" "foo.bar",
-        "e:sessions/error.098preaggr@none",
     ],
 )
 def test_invalid_mri_schema_regex(name):
diff --git a/tests/snuba/api/endpoints/test_organization_measurements_meta.py b/tests/snuba/api/endpoints/test_organization_measurements_meta.py
--- a/tests/snuba/api/endpoints/test_organization_measurements_meta.py
+++ b/tests/snuba/api/endpoints/test_organization_measurements_meta.py
@@ -71,6 +71,80 @@ def test_simple(self):
             }
         }
 
+    def test_measurements_with_numbers_in_name(self):
+        self.store_transaction_metric(
+            1,
+            metric="measurements.something_custom",
+            internal_metric="d:transactions/measurements.1234567890.abcdef@millisecond",
+            entity="metrics_distributions",
+            timestamp=self.day_ago + timedelta(hours=1, minutes=0),
+        )
+        response = self.do_request(
+            {
+                "project": self.project.id,
+                "statsPeriod": "14d",
+            }
+        )
+        assert response.status_code == 200, response.content
+        assert response.data == {
+            "measurements.1234567890.abcdef": {
+                "functions": [
+                    "apdex",
+                    "avg",
+                    "p50",
+                    "p75",
+                    "p90",
+                    "p95",
+                    "p99",
+                    "p100",
+                    "max",
+                    "min",
+                    "sum",
+                    "percentile",
+                    "http_error_count",
+                    "http_error_rate",
+                ],
+                "unit": "millisecond",
+            }
+        }
+
+    def test_measurements_with_lots_of_periods(self):
+        self.store_transaction_metric(
+            1,
+            metric="measurements.something_custom",
+            internal_metric="d:transactions/measurements.a.b.c.d.e.f.g@millisecond",
+            entity="metrics_distributions",
+            timestamp=self.day_ago + timedelta(hours=1, minutes=0),
+        )
+        response = self.do_request(
+            {
+                "project": self.project.id,
+                "statsPeriod": "14d",
+            }
+        )
+        assert response.status_code == 200, response.content
+        assert response.data == {
+            "measurements.a.b.c.d.e.f.g": {
+                "functions": [
+                    "apdex",
+                    "avg",
+                    "p50",
+                    "p75",
+                    "p90",
+                    "p95",
+                    "p99",
+                    "p100",
+                    "max",
+                    "min",
+                    "sum",
+                    "percentile",
+                    "http_error_count",
+                    "http_error_rate",
+                ],
+                "unit": "millisecond",
+            }
+        }
+
     def test_metric_outside_query_daterange(self):
         self.store_transaction_metric(
             1,