Browse Source

feat(starfish): Add ttid & ttfd contribution functions (#60481)

This adds support for determining if a span
contributed to ttid or ttfd on mobile.
Shruthi 1 year ago
parent
commit
a6e36ddd4f

+ 98 - 0
src/sentry/search/events/datasets/spans_metrics.py

@@ -357,6 +357,58 @@ class SpansMetricsDatasetConfig(DatasetConfig):
                     snql_distribution=self._resolve_http_error_count,
                     snql_distribution=self._resolve_http_error_count,
                     default_result_type="integer",
                     default_result_type="integer",
                 ),
                 ),
+                fields.MetricsFunction(
+                    "ttid_contribution_rate",
+                    snql_distribution=lambda args, alias: function_aliases.resolve_division(
+                        self._resolve_ttid_count(args),
+                        Function(
+                            "countIf",
+                            [
+                                Column("value"),
+                                Function(
+                                    "equals",
+                                    [
+                                        Column("metric_id"),
+                                        self.resolve_metric("span.self_time"),
+                                    ],
+                                ),
+                            ],
+                        ),
+                        alias,
+                    ),
+                    default_result_type="percentage",
+                ),
+                fields.MetricsFunction(
+                    "ttid_count",
+                    snql_distribution=self._resolve_ttid_count,
+                    default_result_type="integer",
+                ),
+                fields.MetricsFunction(
+                    "ttfd_contribution_rate",
+                    snql_distribution=lambda args, alias: function_aliases.resolve_division(
+                        self._resolve_ttfd_count(args),
+                        Function(
+                            "countIf",
+                            [
+                                Column("value"),
+                                Function(
+                                    "equals",
+                                    [
+                                        Column("metric_id"),
+                                        self.resolve_metric("span.self_time"),
+                                    ],
+                                ),
+                            ],
+                        ),
+                        alias,
+                    ),
+                    default_result_type="percentage",
+                ),
+                fields.MetricsFunction(
+                    "ttfd_count",
+                    snql_distribution=self._resolve_ttfd_count,
+                    default_result_type="integer",
+                ),
                 fields.MetricsFunction(
                 fields.MetricsFunction(
                     "avg_compare",
                     "avg_compare",
                     required_args=[
                     required_args=[
@@ -563,6 +615,52 @@ class SpansMetricsDatasetConfig(DatasetConfig):
             alias,
             alias,
         )
         )
 
 
+    def _resolve_ttid_count(
+        self,
+        _: Mapping[str, Union[str, Column, SelectType, int, float]],
+        alias: Optional[str] = None,
+    ) -> SelectType:
+        return self._resolve_count_if(
+            Function(
+                "equals",
+                [
+                    Column("metric_id"),
+                    self.resolve_metric("span.self_time"),
+                ],
+            ),
+            Function(
+                "equals",
+                [
+                    self.builder.column("ttid"),
+                    self.builder.resolve_tag_value("ttid"),
+                ],
+            ),
+            alias,
+        )
+
+    def _resolve_ttfd_count(
+        self,
+        _: Mapping[str, Union[str, Column, SelectType, int, float]],
+        alias: Optional[str] = None,
+    ) -> SelectType:
+        return self._resolve_count_if(
+            Function(
+                "equals",
+                [
+                    Column("metric_id"),
+                    self.resolve_metric("span.self_time"),
+                ],
+            ),
+            Function(
+                "equals",
+                [
+                    self.builder.column("ttfd"),
+                    self.builder.resolve_tag_value("ttfd"),
+                ],
+            ),
+            alias,
+        )
+
     def _resolve_epm(
     def _resolve_epm(
         self,
         self,
         args: Mapping[str, Union[str, Column, SelectType, int, float]],
         args: Mapping[str, Union[str, Column, SelectType, int, float]],

+ 49 - 0
tests/snuba/api/endpoints/test_organization_events_span_metrics.py

@@ -375,6 +375,55 @@ class OrganizationEventsMetricsEnhancedPerformanceEndpointTest(MetricsEnhancedPe
         assert meta["fields"]["http_error_count()"] == "integer"
         assert meta["fields"]["http_error_count()"] == "integer"
         assert meta["fields"]["http_error_rate()"] == "percentage"
         assert meta["fields"]["http_error_rate()"] == "percentage"
 
 
+    def test_ttid_rate_and_count(self):
+        for _ in range(8):
+            self.store_span_metric(
+                1,
+                internal_metric=constants.SELF_TIME_LIGHT,
+                tags={"ttid": "ttid", "ttfd": "ttfd"},
+                timestamp=self.min_ago,
+            )
+        self.store_span_metric(
+            1,
+            internal_metric=constants.SELF_TIME_LIGHT,
+            tags={"ttfd": "ttfd", "ttid": ""},
+            timestamp=self.min_ago,
+        )
+        self.store_span_metric(
+            1,
+            internal_metric=constants.SELF_TIME_LIGHT,
+            tags={"ttfd": "", "ttid": ""},
+            timestamp=self.min_ago,
+        )
+        response = self.do_request(
+            {
+                "field": [
+                    "ttid_contribution_rate()",
+                    "ttid_count()",
+                    "ttfd_contribution_rate()",
+                    "ttfd_count()",
+                ],
+                "query": "",
+                "orderby": ["-ttid_contribution_rate()"],
+                "project": self.project.id,
+                "dataset": "spansMetrics",
+                "statsPeriod": "10m",
+            }
+        )
+        assert response.status_code == 200, response.content
+        data = response.data["data"]
+        meta = response.data["meta"]
+        assert len(data) == 1
+        assert data[0]["ttid_contribution_rate()"] == 0.8
+        assert data[0]["ttid_count()"] == 8
+        assert data[0]["ttfd_contribution_rate()"] == 0.9
+        assert data[0]["ttfd_count()"] == 9
+        assert meta["dataset"] == "spansMetrics"
+        assert meta["fields"]["ttid_count()"] == "integer"
+        assert meta["fields"]["ttid_contribution_rate()"] == "percentage"
+        assert meta["fields"]["ttfd_count()"] == "integer"
+        assert meta["fields"]["ttfd_contribution_rate()"] == "percentage"
+
     def test_use_self_time_light(self):
     def test_use_self_time_light(self):
         self.store_span_metric(
         self.store_span_metric(
             100,
             100,