Skip to content

Commit 18fabc4

Browse files
narsaynorathgeorge-sentry
authored andcommitted
feat(tracemetrics): Bypass metric field validation for equations (#112479)
We enforce that there's a `metric` payload for saved queries, but when a user is plotting an equation, there can be multiple `metric`s involved, so this field no longer makes sense. This PR relaxes the constraint so `metric` can be skipped if the user is querying an equation (i.e. we check if there's the `equation|` prefix)
1 parent 2f2eeb0 commit 18fabc4

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/sentry/explore/endpoints/serializers.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from rest_framework.serializers import ListField
55

66
from sentry.constants import ALL_ACCESS_PROJECTS
7+
from sentry.discover.arithmetic import is_equation
78
from sentry.explore.models import ExploreSavedQueryDataset
89
from sentry.utils.dates import parse_stats_period, validate_interval
910

@@ -222,9 +223,17 @@ def validate(self, data):
222223
raise serializers.ValidationError(
223224
"Metric field is only allowed for metrics dataset"
224225
)
225-
if data["dataset"] == "metrics" and "metric" not in q:
226+
227+
# the metrics field is only required for non-equation queries
228+
y_axes = [
229+
y_axis
230+
for aggregate_field in q.get("aggregateField") or []
231+
for y_axis in aggregate_field.get("yAxes") or []
232+
]
233+
is_equations = len(y_axes) > 0 and all(is_equation(y_axis) for y_axis in y_axes)
234+
if data["dataset"] == "metrics" and not is_equations and "metric" not in q:
226235
raise serializers.ValidationError(
227-
"Metric field is required for metrics dataset"
236+
"Metric field is required for non-equation queries on the metrics dataset"
228237
)
229238
inner_query = {}
230239
for key in inner_query_keys:

tests/sentry/explore/endpoints/test_explore_saved_queries.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,9 @@ def test_post_metrics_dataset_requires_metric_field(self) -> None:
12731273
},
12741274
)
12751275
assert response.status_code == 400, response.content
1276-
assert "Metric field is required for metrics dataset" in str(response.data)
1276+
assert "Metric field is required for non-equation queries on the metrics dataset" in str(
1277+
response.data
1278+
)
12771279

12781280
def test_save_with_start_and_end_time(self) -> None:
12791281
with self.feature(self.features):
@@ -1391,3 +1393,25 @@ def test_post_with_empty_query_is_rejected(self) -> None:
13911393
},
13921394
)
13931395
assert response.status_code == 400
1396+
1397+
def test_post_with_equation_is_accepted(self) -> None:
1398+
with self.feature(self.features):
1399+
response = self.client.post(
1400+
self.url,
1401+
{
1402+
"name": "Equation query",
1403+
"projects": self.project_ids,
1404+
"dataset": "metrics",
1405+
"query": [
1406+
{
1407+
"aggregateField": [{"yAxes": ["equation|A + B"], "chartType": 1}],
1408+
"mode": "samples",
1409+
"fields": ["A", "B"],
1410+
"orderby": "-timestamp",
1411+
},
1412+
],
1413+
},
1414+
)
1415+
assert response.status_code == 201, response.content
1416+
data = response.data
1417+
assert data["query"][0].get("metric") is None

0 commit comments

Comments
 (0)