Skip to content

fix(dashboard): OnDemand widget creation also includes transaction type #79059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/sentry/api/serializers/rest_framework/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ def validate(self, data):

if (
ondemand_feature
and data.get("widget_type") == DashboardWidgetTypes.DISCOVER
and data.get("widget_type")
in [DashboardWidgetTypes.DISCOVER, DashboardWidgetTypes.TRANSACTION_LIKE]
and not query.get("on_demand_extraction_disabled", False)
):
if query.get("columns"):
Expand Down Expand Up @@ -654,7 +655,10 @@ def create_widget(self, dashboard, widget_data, order):

DashboardWidgetQuery.objects.bulk_create(new_queries)

if widget.widget_type == DashboardWidgetTypes.DISCOVER:
if widget.widget_type in [
DashboardWidgetTypes.DISCOVER,
DashboardWidgetTypes.TRANSACTION_LIKE,
]:
self._check_query_cardinality(new_queries)

def _check_query_cardinality(self, new_queries: Sequence[DashboardWidgetQuery]):
Expand Down Expand Up @@ -734,7 +738,10 @@ def update_widget_queries(self, widget, data):
raise serializers.ValidationError("You cannot use a query not owned by this widget")
DashboardWidgetQuery.objects.bulk_create(new_queries)

if widget.widget_type == DashboardWidgetTypes.DISCOVER:
if widget.widget_type in [
DashboardWidgetTypes.DISCOVER,
DashboardWidgetTypes.TRANSACTION_LIKE,
]:
self._check_query_cardinality(new_queries + update_queries)

def update_widget_query(self, query, data, order):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,33 @@ def test_update_dashboard_with_widget_filter_requiring_environment(self):
)
assert response.status_code == 200, response.data


class OrganizationDashboardDetailsOnDemandTest(OrganizationDashboardDetailsTestCase):
widget_type = DashboardWidgetTypes.DISCOVER

def setUp(self):
super().setUp()
self.project = self.create_project()
self.create_user_member_role()
self.widget_3 = DashboardWidget.objects.create(
dashboard=self.dashboard,
order=2,
title="Widget 3",
display_type=DashboardWidgetDisplayTypes.LINE_CHART,
widget_type=self.widget_type,
)
self.widget_4 = DashboardWidget.objects.create(
dashboard=self.dashboard,
order=3,
title="Widget 4",
display_type=DashboardWidgetDisplayTypes.LINE_CHART,
widget_type=self.widget_type,
)
self.widget_ids = [self.widget_1.id, self.widget_2.id, self.widget_3.id, self.widget_4.id]

def get_widget_queries(self, widget):
return DashboardWidgetQuery.objects.filter(widget=widget).order_by("order")

def test_ondemand_without_flags(self):
data: dict[str, Any] = {
"title": "First dashboard",
Expand All @@ -1777,6 +1804,7 @@ def test_ondemand_without_flags(self):
"title": "Errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "Errors",
Expand Down Expand Up @@ -1813,6 +1841,7 @@ def test_ondemand_with_unapplicable_query(self):
"title": "Errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "Errors",
Expand Down Expand Up @@ -1850,6 +1879,7 @@ def test_ondemand_with_flags(self):
"title": "Errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "Errors",
Expand Down Expand Up @@ -1888,6 +1918,7 @@ def test_ondemand_hits_spec_limit(self, mock_max):
"title": "Errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "Errors",
Expand Down Expand Up @@ -1932,6 +1963,7 @@ def test_ondemand_hits_card_limit(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "errors",
Expand Down Expand Up @@ -1973,6 +2005,7 @@ def test_ondemand_updates_existing_widget(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "errors",
Expand Down Expand Up @@ -2009,6 +2042,7 @@ def test_ondemand_updates_existing_widget(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"id": str(queries[0].id),
Expand Down Expand Up @@ -2055,6 +2089,7 @@ def test_ondemand_updates_new_widget(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "errors",
Expand Down Expand Up @@ -2091,6 +2126,7 @@ def test_ondemand_updates_new_widget(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
# without id here we'll make a new query and delete the old one
Expand Down Expand Up @@ -2137,6 +2173,7 @@ def test_cardinality_precedence_over_feature_checks(self, mock_query):
"title": "errors per project",
"displayType": "table",
"interval": "5m",
"widgetType": DashboardWidgetTypes.get_type_name(self.widget_type),
"queries": [
{
"name": "errors",
Expand Down Expand Up @@ -2267,6 +2304,13 @@ def test_add_widget_with_split_widget_type_writes_to_split_decision(self):
assert widgets[2].discover_widget_split is None


class OrganizationDashboardDetailsOnDemandTransactionLikeTest(
OrganizationDashboardDetailsOnDemandTest
):
# Re-run the on-demand tests with the transaction-like widget type
widget_type = DashboardWidgetTypes.TRANSACTION_LIKE


class OrganizationDashboardVisitTest(OrganizationDashboardDetailsTestCase):
def url(self, dashboard_id):
return reverse(
Expand Down
Loading