diff --git a/src/sentry/api/bases/organization_events.py b/src/sentry/api/bases/organization_events.py index f06be16e9d616c..ee9302e6c304c4 100644 --- a/src/sentry/api/bases/organization_events.py +++ b/src/sentry/api/bases/organization_events.py @@ -25,6 +25,7 @@ from sentry.discover.models import DatasetSourcesTypes, DiscoverSavedQueryTypes from sentry.exceptions import InvalidSearchQuery from sentry.models.dashboard_widget import DashboardWidgetTypes +from sentry.models.dashboard_widget import DatasetSourcesTypes as DashboardDatasetSourcesTypes from sentry.models.group import Group from sentry.models.organization import Organization from sentry.models.project import Project @@ -262,6 +263,7 @@ def save_split_decision(self, widget, has_errors, has_transactions_data): and widget.discover_widget_split != new_discover_widget_split ): widget.discover_widget_split = new_discover_widget_split + widget.dataset_source = DashboardDatasetSourcesTypes.INFERRED.value widget.save() return new_discover_widget_split diff --git a/src/sentry/api/serializers/models/dashboard.py b/src/sentry/api/serializers/models/dashboard.py index 52c90df7b8e580..11cf0daad313ca 100644 --- a/src/sentry/api/serializers/models/dashboard.py +++ b/src/sentry/api/serializers/models/dashboard.py @@ -5,6 +5,7 @@ from sentry import features from sentry.api.serializers import Serializer, register, serialize from sentry.constants import ALL_ACCESS_PROJECTS +from sentry.discover.models import DatasetSourcesTypes from sentry.models.dashboard import Dashboard from sentry.models.dashboard_widget import ( DashboardWidget, @@ -17,6 +18,8 @@ from sentry.users.services.user.service import user_service from sentry.utils.dates import outside_retention_with_modified_start, parse_timestamp +DATASET_SOURCES = dict(DatasetSourcesTypes.as_choices()) + @register(DashboardWidget) class DashboardWidgetSerializer(Serializer): @@ -67,6 +70,7 @@ def serialize(self, obj, attrs, user, **kwargs): # Default to discover type if null "widgetType": widget_type, "layout": obj.detail.get("layout") if obj.detail else None, + "datasetSource": DATASET_SOURCES[obj.dataset_source], } diff --git a/tests/sentry/api/endpoints/test_organization_dashboard_details.py b/tests/sentry/api/endpoints/test_organization_dashboard_details.py index a41934ac2a75ce..0fb1d2cf1df8a2 100644 --- a/tests/sentry/api/endpoints/test_organization_dashboard_details.py +++ b/tests/sentry/api/endpoints/test_organization_dashboard_details.py @@ -6,6 +6,7 @@ from django.urls import reverse +from sentry.discover.models import DatasetSourcesTypes from sentry.models.dashboard import Dashboard, DashboardTombstone from sentry.models.dashboard_widget import ( DashboardWidget, @@ -262,6 +263,47 @@ def test_dashboard_widget_type_returns_split_decision(self): assert response.data["widgets"][1]["widgetType"] == "transaction-like" assert response.data["widgets"][2]["widgetType"] == "discover" + def test_dashboard_widget_returns_dataset_source(self): + dashboard = Dashboard.objects.create( + title="Dashboard With Dataset Source", + created_by_id=self.user.id, + organization=self.organization, + ) + DashboardWidget.objects.create( + dashboard=dashboard, + order=0, + title="error widget", + display_type=DashboardWidgetDisplayTypes.LINE_CHART, + widget_type=DashboardWidgetTypes.DISCOVER, + interval="1d", + detail={"layout": {"x": 0, "y": 0, "w": 1, "h": 1, "minH": 2}}, + dataset_source=DatasetSourcesTypes.INFERRED.value, + ) + + response = self.do_request("get", self.url(dashboard.id)) + assert response.status_code == 200, response.content + assert response.data["widgets"][0]["datasetSource"] == "inferred" + + def test_dashboard_widget_default_dataset_source_is_unknown(self): + dashboard = Dashboard.objects.create( + title="Dashboard Without", + created_by_id=self.user.id, + organization=self.organization, + ) + DashboardWidget.objects.create( + dashboard=dashboard, + order=0, + title="error widget", + display_type=DashboardWidgetDisplayTypes.LINE_CHART, + widget_type=DashboardWidgetTypes.DISCOVER, + interval="1d", + detail={"layout": {"x": 0, "y": 0, "w": 1, "h": 1, "minH": 2}}, + ) + + response = self.do_request("get", self.url(dashboard.id)) + assert response.status_code == 200, response.content + assert response.data["widgets"][0]["datasetSource"] == "unknown" + class OrganizationDashboardDetailsDeleteTest(OrganizationDashboardDetailsTestCase): def test_delete(self): diff --git a/tests/snuba/api/endpoints/test_organization_events_mep.py b/tests/snuba/api/endpoints/test_organization_events_mep.py index bee6706161c9db..398856c353d4aa 100644 --- a/tests/snuba/api/endpoints/test_organization_events_mep.py +++ b/tests/snuba/api/endpoints/test_organization_events_mep.py @@ -5,7 +5,7 @@ from django.urls import reverse from rest_framework.response import Response -from sentry.discover.models import TeamKeyTransaction +from sentry.discover.models import DatasetSourcesTypes, TeamKeyTransaction from sentry.models.dashboard_widget import DashboardWidgetTypes from sentry.models.projectteam import ProjectTeam from sentry.models.transaction_threshold import ( @@ -3679,6 +3679,7 @@ def test_split_decision_for_errors_widget(self): widget.refresh_from_db() assert widget.discover_widget_split == DashboardWidgetTypes.ERROR_EVENTS + assert widget.dataset_source == DatasetSourcesTypes.INFERRED.value def test_split_decision_for_transactions_widget(self): transaction_data = load_data("transaction", timestamp=before_now(minutes=1)) @@ -3711,6 +3712,7 @@ def test_split_decision_for_transactions_widget(self): widget.refresh_from_db() assert widget.discover_widget_split == DashboardWidgetTypes.TRANSACTION_LIKE + assert widget.dataset_source == DatasetSourcesTypes.INFERRED.value def test_split_decision_for_ambiguous_widget_without_data(self): _, widget, __ = create_widget( @@ -3736,6 +3738,7 @@ def test_split_decision_for_ambiguous_widget_without_data(self): widget.refresh_from_db() assert widget.discover_widget_split is None + assert widget.dataset_source == DatasetSourcesTypes.UNKNOWN.value def test_split_decision_for_ambiguous_widget_with_data(self): # Store a transaction