Browse Source

fix(custom-measurments): Handle measurement names with numbers (#62580)

- This updates the measurements regex so it can handle measurement names
with numbers in them
- Fixes #52758
William Mak 1 year ago
parent
commit
da6aac3a9f

+ 2 - 2
src/sentry/snuba/metrics/naming_layer/mri.py

@@ -49,9 +49,9 @@ from sentry.snuba.metrics.utils import (
 
 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}$")

+ 0 - 1
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):

+ 74 - 0
tests/snuba/api/endpoints/test_organization_measurements_meta.py

@@ -71,6 +71,80 @@ class OrganizationMeasurementsMetaEndpoint(MetricsEnhancedPerformanceTestCase):
             }
         }
 
+    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,