diff --git a/src/sentry/dashboards/endpoints/organization_dashboards.py b/src/sentry/dashboards/endpoints/organization_dashboards.py index d1e8322615f5..1ca07ab93139 100644 --- a/src/sentry/dashboards/endpoints/organization_dashboards.py +++ b/src/sentry/dashboards/endpoints/organization_dashboards.py @@ -5,17 +5,7 @@ import sentry_sdk from django.db import IntegrityError, router, transaction -from django.db.models import ( - Case, - Exists, - F, - IntegerField, - OrderBy, - OuterRef, - Subquery, - Value, - When, -) +from django.db.models import Case, Exists, F, IntegerField, OrderBy, OuterRef, Subquery, Value, When from drf_spectacular.utils import extend_schema from rest_framework import status from rest_framework.request import Request @@ -104,6 +94,7 @@ class PrebuiltDashboard(TypedDict, total=False): title: Required[str] hidden: bool pre_favorited: bool + required_feature_flags: list[str] # Prebuilt dashboards store minimal fields in the database. The actual dashboard and widget settings are @@ -240,6 +231,7 @@ class PrebuiltDashboard(TypedDict, total=False): { "prebuilt_id": PrebuiltDashboardId.NODE_RUNTIME_METRICS, "title": "Node.js Runtime Metrics", + "required_feature_flags": ["organizations:tracemetrics-enabled"], }, ] @@ -263,6 +255,10 @@ def get_enabled_prebuilt_dashboards( dashboard for dashboard in all_prebuilt_dashboards if dashboard["prebuilt_id"] in enabled_prebuilt_dashboard_ids + and all( + features.has(feature, organization) + for feature in dashboard.get("required_feature_flags", []) + ) ] diff --git a/tests/sentry/dashboards/endpoints/test_organization_dashboards.py b/tests/sentry/dashboards/endpoints/test_organization_dashboards.py index 65454f7de255..5a7891ec7990 100644 --- a/tests/sentry/dashboards/endpoints/test_organization_dashboards.py +++ b/tests/sentry/dashboards/endpoints/test_organization_dashboards.py @@ -2416,8 +2416,13 @@ def test_hidden_prebuilt_dashboards_included_with_show_hidden_filter(self) -> No assert PrebuiltDashboardId.BACKEND_QUERIES_SUMMARY in prebuilt_ids_in_response def test_node_runtime_metrics_prebuilt_dashboard_sync(self) -> None: - """The Node.js Runtime Metrics prebuilt dashboard syncs when enabled via options.""" - with self.feature("organizations:dashboards-prebuilt-insights-dashboards"): + """The Node.js Runtime Metrics dashboard syncs when metrics and its option are enabled.""" + with self.feature( + [ + "organizations:dashboards-prebuilt-insights-dashboards", + "organizations:tracemetrics-enabled", + ] + ): with override_options( {"dashboards.prebuilt-dashboard-ids": [PrebuiltDashboardId.NODE_RUNTIME_METRICS]} ): @@ -2437,6 +2442,23 @@ def test_node_runtime_metrics_prebuilt_dashboard_sync(self) -> None: ] assert len(prebuilt_in_response) == 1 + def test_node_runtime_metrics_prebuilt_dashboard_not_synced_without_metrics(self) -> None: + with self.feature("organizations:dashboards-prebuilt-insights-dashboards"): + with override_options( + {"dashboards.prebuilt-dashboard-ids": [PrebuiltDashboardId.NODE_RUNTIME_METRICS]} + ): + response = self.do_request("get", self.url) + assert response.status_code == 200 + + assert not Dashboard.objects.filter( + organization=self.organization, + prebuilt_id=PrebuiltDashboardId.NODE_RUNTIME_METRICS, + ).exists() + assert all( + dashboard.get("prebuiltId") != PrebuiltDashboardId.NODE_RUNTIME_METRICS + for dashboard in response.data + ) + def test_endpoint_creates_pre_favorited_prebuilt_dashboards(self) -> None: assert ( DashboardFavoriteUser.objects.filter(