1212from rest_framework .exceptions import ParseError , ValidationError
1313from rest_framework .request import Request
1414from rest_framework .response import Response
15- from snuba_sdk import And , BooleanCondition , BooleanOp , Column , Condition , Function , Op , Or
15+ from snuba_sdk import BooleanCondition , BooleanOp , Column , Condition , Function , Op
1616from urllib3 .exceptions import ReadTimeoutError
1717
1818from sentry import features , options
3535)
3636from sentry .search .events .constants import TIMEOUT_SPAN_ERROR_MESSAGE
3737from sentry .search .events .types import QueryBuilderConfig , SnubaParams , WhereType
38- from sentry .sentry_metrics .querying .samples_list import SpanKey , get_sample_list_executor_cls
3938from sentry .snuba import discover , spans_indexed
4039from sentry .snuba .dataset import Dataset
4140from sentry .snuba .referrer import Referrer
@@ -311,7 +310,9 @@ def get(self, request: Request, organization: Organization) -> Response:
311310 zerofill = not (
312311 request .GET .get ("withoutZerofill" ) == "1"
313312 and features .get (
314- "organizations:performance-chart-interpolation" , organization , actor = request .user
313+ "organizations:performance-chart-interpolation" ,
314+ organization ,
315+ actor = request .user ,
315316 )
316317 )
317318
@@ -499,76 +500,8 @@ def get_traces_matching_conditions(
499500 self ,
500501 snuba_params : SnubaParams ,
501502 ) -> tuple [datetime , datetime , list [str ]]:
502- if self .mri is not None :
503- sentry_sdk .set_tag ("mri" , self .mri )
504- return self .get_traces_matching_metric_conditions (snuba_params )
505-
506503 return self .get_traces_matching_span_conditions (snuba_params )
507504
508- def get_traces_matching_metric_conditions (
509- self ,
510- snuba_params : SnubaParams ,
511- ) -> tuple [datetime , datetime , list [str ]]:
512- assert self .mri is not None
513-
514- executor_cls = get_sample_list_executor_cls (self .mri )
515- if executor_cls is None :
516- raise ParseError (detail = f"Unsupported MRI: { self .mri } " )
517-
518- executor = executor_cls (
519- mri = self .mri ,
520- snuba_params = snuba_params ,
521- fields = ["trace" ],
522- max = self .metrics_max ,
523- min = self .metrics_min ,
524- operation = self .metrics_operation ,
525- query = self .metrics_query ,
526- referrer = Referrer .API_TRACE_EXPLORER_METRICS_SPANS_LIST ,
527- )
528-
529- trace_ids , timestamps = executor .get_matching_traces (MAX_SNUBA_RESULTS )
530-
531- min_timestamp = snuba_params .end
532- max_timestamp = snuba_params .start
533- assert min_timestamp is not None
534- assert max_timestamp is not None
535-
536- for timestamp in timestamps :
537- min_timestamp = min (min_timestamp , timestamp )
538- max_timestamp = max (max_timestamp , timestamp )
539-
540- if not trace_ids or min_timestamp > max_timestamp :
541- return min_timestamp , max_timestamp , []
542-
543- self .refine_params (min_timestamp , max_timestamp )
544-
545- if self .user_queries :
546- # If there are user queries, further refine the trace ids by applying them
547- # leaving us with only traces where the metric exists and matches the user
548- # queries.
549- (
550- min_timestamp ,
551- max_timestamp ,
552- trace_ids ,
553- ) = self .get_traces_matching_span_conditions_in_traces (snuba_params , trace_ids )
554-
555- if not trace_ids :
556- return min_timestamp , max_timestamp , []
557- else :
558- # No user queries so take the first N trace ids as our list
559- min_timestamp = snuba_params .end
560- max_timestamp = snuba_params .start
561- assert min_timestamp is not None
562- assert max_timestamp is not None
563-
564- trace_ids = trace_ids [: self .limit ]
565- timestamps = timestamps [: self .limit ]
566- for timestamp in timestamps :
567- min_timestamp = min (min_timestamp , timestamp )
568- max_timestamp = max (max_timestamp , timestamp )
569-
570- return min_timestamp , max_timestamp , trace_ids
571-
572505 def get_traces_matching_span_conditions (
573506 self ,
574507 snuba_params : SnubaParams ,
@@ -1248,54 +1181,20 @@ def __init__(
12481181
12491182 def execute (self , offset : int , limit : int ):
12501183 with handle_span_query_errors ():
1251- span_keys = self .get_metrics_span_keys ()
1252-
1253- with handle_span_query_errors ():
1254- spans = self .get_user_spans (
1184+ return self .get_user_spans (
12551185 self .snuba_params ,
1256- span_keys ,
12571186 offset = offset ,
12581187 limit = limit ,
12591188 )
12601189
1261- return spans
1262-
1263- def get_metrics_span_keys (self ) -> list [SpanKey ] | None :
1264- if self .mri is None :
1265- return None
1266-
1267- executor_cls = get_sample_list_executor_cls (self .mri )
1268- if executor_cls is None :
1269- raise ParseError (detail = f"Unsupported MRI: { self .mri } " )
1270-
1271- executor = executor_cls (
1272- mri = self .mri ,
1273- snuba_params = self .snuba_params ,
1274- fields = ["trace" ],
1275- max = self .metrics_max ,
1276- min = self .metrics_min ,
1277- operation = self .metrics_operation ,
1278- query = self .metrics_query ,
1279- referrer = Referrer .API_TRACE_EXPLORER_METRICS_SPANS_LIST ,
1280- )
1281-
1282- span_keys = executor .get_matching_spans_from_traces (
1283- [self .trace_id ],
1284- MAX_SNUBA_RESULTS ,
1285- )
1286-
1287- return span_keys
1288-
12891190 def get_user_spans (
12901191 self ,
12911192 snuba_params : SnubaParams ,
1292- span_keys : list [SpanKey ] | None ,
12931193 limit : int ,
12941194 offset : int ,
12951195 ):
12961196 user_spans_query = self .get_user_spans_query (
12971197 snuba_params ,
1298- span_keys ,
12991198 limit = limit ,
13001199 offset = offset ,
13011200 )
@@ -1313,15 +1212,14 @@ def get_user_spans(
13131212 def get_user_spans_query (
13141213 self ,
13151214 snuba_params : SnubaParams ,
1316- span_keys : list [SpanKey ] | None ,
13171215 limit : int ,
13181216 offset : int ,
13191217 ) -> BaseQueryBuilder :
13201218 if self .dataset == Dataset .EventsAnalyticsPlatform :
13211219 # span_keys is not supported in EAP mode because that's a legacy
13221220 # code path to support metrics that no longer exists
13231221 return self .get_user_spans_query_eap (snuba_params , limit , offset )
1324- return self .get_user_spans_query_indexed (snuba_params , span_keys , limit , offset )
1222+ return self .get_user_spans_query_indexed (snuba_params , limit , offset )
13251223
13261224 def get_user_spans_query_eap (
13271225 self ,
@@ -1383,7 +1281,6 @@ def get_user_spans_query_eap(
13831281 def get_user_spans_query_indexed (
13841282 self ,
13851283 snuba_params : SnubaParams ,
1386- span_keys : list [SpanKey ] | None ,
13871284 limit : int ,
13881285 offset : int ,
13891286 ) -> BaseQueryBuilder :
@@ -1411,69 +1308,30 @@ def get_user_spans_query_indexed(
14111308
14121309 conditions = []
14131310
1414- if span_keys is None :
1415- # Next we have to turn the user queries into the appropriate conditions in
1416- # the SnQL that we produce.
1311+ # Next we have to turn the user queries into the appropriate conditions in
1312+ # the SnQL that we produce.
14171313
1418- # There are multiple sets of user conditions that needs to be satisfied
1419- # and if a span satisfy any of them, it should be considered.
1420- #
1421- # To handle this use case, we want to OR all the user specified
1422- # conditions together in this query.
1423- for where in user_conditions :
1424- if len (where ) > 1 :
1425- conditions .append (BooleanCondition (op = BooleanOp .AND , conditions = where ))
1426- elif len (where ) == 1 :
1427- conditions .append (where [0 ])
1428-
1429- if len (conditions ) > 1 :
1430- # More than 1 set of conditions were specified, we want to show
1431- # spans that match any 1 of them so join the conditions with `OR`s.
1432- user_spans_query .add_conditions (
1433- [BooleanCondition (op = BooleanOp .OR , conditions = conditions )]
1434- )
1435- elif len (conditions ) == 1 :
1436- # Only 1 set of user conditions were specified, simply insert them into
1437- # the final query.
1438- user_spans_query .add_conditions ([conditions [0 ]])
1439- else :
1440- # Next if there are known span_keys, we only try to fetch those spans
1441- # This are the additional conditions to better take advantage of the ORDER BY
1442- # on the spans table. This creates a list of conditions to be `OR`ed together
1443- # that can will be used by ClickHouse to narrow down the granules.
1444- #
1445- # The span ids are not in this condition because they are more effective when
1446- # specified within the `PREWHERE` clause. So, it's in a separate condition.
1447- conditions = [
1448- And (
1449- [
1450- Condition (user_spans_query .column ("span.group" ), Op .EQ , key .group ),
1451- Condition (
1452- user_spans_query .column ("timestamp" ),
1453- Op .EQ ,
1454- datetime .fromisoformat (key .timestamp ),
1455- ),
1456- ]
1457- )
1458- for key in span_keys
1459- ]
1314+ # There are multiple sets of user conditions that needs to be satisfied
1315+ # and if a span satisfy any of them, it should be considered.
1316+ #
1317+ # To handle this use case, we want to OR all the user specified
1318+ # conditions together in this query.
1319+ for where in user_conditions :
1320+ if len (where ) > 1 :
1321+ conditions .append (BooleanCondition (op = BooleanOp .AND , conditions = where ))
1322+ elif len (where ) == 1 :
1323+ conditions .append (where [0 ])
14601324
1461- if len (conditions ) == 1 :
1462- order_by_condition = conditions [0 ]
1463- else :
1464- order_by_condition = Or (conditions )
1465-
1466- # Using `IN` combined with putting the list in a SnQL "tuple" triggers an optimizer
1467- # in snuba where it
1468- # 1. moves the condition into the `PREWHERE` clause
1469- # 2. maps the ids to the underlying UInt64 and uses the bloom filter index
1470- span_id_condition = Condition (
1471- user_spans_query .column ("id" ),
1472- Op .IN ,
1473- Function ("tuple" , [key .span_id for key in span_keys ]),
1325+ if len (conditions ) > 1 :
1326+ # More than 1 set of conditions were specified, we want to show
1327+ # spans that match any 1 of them so join the conditions with `OR`s.
1328+ user_spans_query .add_conditions (
1329+ [BooleanCondition (op = BooleanOp .OR , conditions = conditions )]
14741330 )
1475-
1476- user_spans_query .add_conditions ([order_by_condition , span_id_condition ])
1331+ elif len (conditions ) == 1 :
1332+ # Only 1 set of user conditions were specified, simply insert them into
1333+ # the final query.
1334+ user_spans_query .add_conditions ([conditions [0 ]])
14771335
14781336 return user_spans_query
14791337
0 commit comments