Browse Source

fix(functions): Units on function stats response (#59143)

Using an alias prefix broke the units on the response. Make sure it is
correctly mapped back to the expected aliases with the correct units
set.
Tony Xiao 1 year ago
parent
commit
e0a04bbbf7

+ 6 - 0
src/sentry/search/events/builder/profile_functions.py

@@ -57,10 +57,16 @@ class ProfileFunctionsTimeseriesQueryBuilder(
             column: get_function_alias(function_details.field)
             for column, function_details in self.function_alias_map.items()
         }
+        self.function_alias_map = {
+            alias_mappings.get(column, column): function_details
+            for column, function_details in self.function_alias_map.items()
+        }
         result["data"] = [
             {alias_mappings.get(k, k): v for k, v in item.items()}
             for item in result.get("data", [])
         ]
+        for item in result.get("meta", []):
+            item["name"] = alias_mappings.get(item["name"], item["name"])
         return result
 
     @property

+ 4 - 4
src/sentry/search/events/datasets/profile_functions.py

@@ -243,13 +243,13 @@ class ProfileFunctionsDatasetConfig(DatasetConfig):
                 SnQLFunction(
                     "cpm",  # calls per minute
                     snql_aggregate=lambda args, alias: self._resolve_cpm(args, alias),
-                    default_result_type="integer",
+                    default_result_type="number",
                 ),
                 SnQLFunction(
                     "cpm_before",
                     required_args=[TimestampArg("timestamp")],
                     snql_aggregate=lambda args, alias: self._resolve_cpm_cond(args, alias, "less"),
-                    default_result_type="integer",
+                    default_result_type="number",
                 ),
                 SnQLFunction(
                     "cpm_after",
@@ -257,13 +257,13 @@ class ProfileFunctionsDatasetConfig(DatasetConfig):
                     snql_aggregate=lambda args, alias: self._resolve_cpm_cond(
                         args, alias, "greater"
                     ),
-                    default_result_type="integer",
+                    default_result_type="number",
                 ),
                 SnQLFunction(
                     "cpm_delta",
                     required_args=[TimestampArg("timestamp")],
                     snql_aggregate=self._resolve_cpm_delta,
-                    default_result_type="integer",
+                    default_result_type="number",
                 ),
                 SnQLFunction(
                     "count_unique",

+ 32 - 5
tests/snuba/api/endpoints/test_organization_events_stats.py

@@ -2611,14 +2611,30 @@ class OrganizationEventsStatsProfileFunctionDatasetEndpointTest(
             "start": iso_format(self.three_days_ago),
             "end": iso_format(self.one_day_ago),
             "interval": "1d",
-            "yAxis": "cpm()",
+            "yAxis": ["cpm()", "p95(function.duration)"],
         }
 
         response = self.client.get(self.url, data=data, format="json")
         assert response.status_code == 200, response.content
-        assert sum(row[1][0]["count"] for row in response.data["data"]) == pytest.approx(
+
+        assert sum(row[1][0]["count"] for row in response.data["cpm()"]["data"]) == pytest.approx(
             100 / ((self.one_day_ago - self.three_days_ago).total_seconds() / 60), rel=1e-3
         )
+        assert any(
+            row[1][0]["count"] > 0 for row in response.data["p95(function.duration)"]["data"]
+        )
+
+        for y_axis in ["cpm()", "p95(function.duration)"]:
+            assert response.data[y_axis]["meta"]["fields"] == {
+                "time": "date",
+                "cpm": "number",
+                "p95_function_duration": "duration",
+            }
+            assert response.data[y_axis]["meta"]["units"] == {
+                "time": None,
+                "cpm": None,
+                "p95_function_duration": "nanosecond",
+            }
 
 
 @region_silo_test
@@ -2667,7 +2683,7 @@ class OrganizationEventsStatsTopNEventsProfileFunctionDatasetEndpointTest(
             "field": ["function", "count()"],
             "start": iso_format(self.three_days_ago),
             "end": iso_format(self.one_day_ago),
-            "yAxis": "cpm()",
+            "yAxis": ["cpm()", "p95(function.duration)"],
             "interval": "1d",
             "topEvents": 2,
             "excludeOther": 1,
@@ -2675,9 +2691,20 @@ class OrganizationEventsStatsTopNEventsProfileFunctionDatasetEndpointTest(
 
         response = self.client.get(self.url, data=data, format="json")
         assert response.status_code == 200, response.content
-        assert sum(row[1][0]["count"] for row in response.data["foo"]["data"]) == pytest.approx(
+        assert sum(
+            row[1][0]["count"] for row in response.data["foo"]["cpm()"]["data"]
+        ) == pytest.approx(
             100 / ((self.one_day_ago - self.three_days_ago).total_seconds() / 60), rel=1e-3
         )
-        assert sum(row[1][0]["count"] for row in response.data["bar"]["data"]) == pytest.approx(
+        assert sum(
+            row[1][0]["count"] for row in response.data["bar"]["cpm()"]["data"]
+        ) == pytest.approx(
             10 / ((self.one_day_ago - self.three_days_ago).total_seconds() / 60), rel=1e-3
         )
+
+        assert any(
+            row[1][0]["count"] > 0 for row in response.data["foo"]["p95(function.duration)"]["data"]
+        )
+        assert any(
+            row[1][0]["count"] > 0 for row in response.data["bar"]["p95(function.duration)"]["data"]
+        )