Created
January 9, 2023 15:54
-
-
Save wmak/18bea8802be2a4e3258bdd5b2941381d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/sentry/search/events/builder/metrics.py b/src/sentry/search/events/builder/metrics.py | |
index 019653f227..4e1afa4e53 100644 | |
--- a/src/sentry/search/events/builder/metrics.py | |
+++ b/src/sentry/search/events/builder/metrics.py | |
@@ -43,6 +43,7 @@ from sentry.utils.snuba import DATASETS, Dataset, bulk_snql_query, raw_snql_quer | |
class MetricsQueryBuilder(QueryBuilder): | |
requires_organization_condition = True | |
+ is_alerts_query = False | |
organization_column: str = "organization_id" | |
def __init__( | |
@@ -597,42 +598,40 @@ class MetricsQueryBuilder(QueryBuilder): | |
) or (isinstance(orderby.exp, Function) and orderby.exp.alias == "title"): | |
raise IncompatibleMetricsQuery("Can't orderby tags") | |
- def _run_query_with_metrics_layer(self, query: Query, is_alerts_query: bool = False) -> Any: | |
- from sentry.snuba.metrics.datasource import get_series | |
- from sentry.snuba.metrics.mqb_query_transformer import transform_mqb_query_to_metrics_query | |
- | |
- try: | |
- with sentry_sdk.start_span(op="metric_layer", description="transform_query"): | |
- metric_query = transform_mqb_query_to_metrics_query(query, is_alerts_query) | |
- with sentry_sdk.start_span(op="metric_layer", description="run_query"): | |
- metrics_data = get_series( | |
- projects=self.params.projects, | |
- metrics_query=metric_query, | |
- use_case_id=UseCaseKey.PERFORMANCE | |
- if self.is_performance | |
- else UseCaseKey.RELEASE_HEALTH, | |
- include_meta=True, | |
- ) | |
- except Exception as err: | |
- raise IncompatibleMetricsQuery(err) | |
- with sentry_sdk.start_span(op="metric_layer", description="transform_results"): | |
- # series does some strange stuff to the clickhouse response, turn it back so we can handle it | |
- metric_layer_result: Any = { | |
- "data": [], | |
- "meta": metrics_data["meta"], | |
- } | |
- for group in metrics_data["groups"]: | |
- data = group["by"] | |
- data.update(group["totals"]) | |
- metric_layer_result["data"].append(data) | |
- for meta in metric_layer_result["meta"]: | |
- if data[meta["name"]] is None: | |
- data[meta["name"]] = self.get_default_value(meta["type"]) | |
- return metric_layer_result | |
- | |
def run_query(self, referrer: str, use_cache: bool = False) -> Any: | |
if self.use_metrics_layer: | |
- return self._run_query_with_metrics_layer(query=self.get_snql_query().query) | |
+ from sentry.snuba.metrics.datasource import get_series | |
+ from sentry.snuba.metrics.mqb_query_transformer import transform_mqb_query_to_metrics_query | |
+ | |
+ snuba_query = self.get_snql_query().query | |
+ try: | |
+ with sentry_sdk.start_span(op="metric_layer", description="transform_query"): | |
+ metric_query = transform_mqb_query_to_metrics_query(snuba_query, self.is_alerts_query) | |
+ with sentry_sdk.start_span(op="metric_layer", description="run_query"): | |
+ metrics_data = get_series( | |
+ projects=self.params.projects, | |
+ metrics_query=metric_query, | |
+ use_case_id=UseCaseKey.PERFORMANCE | |
+ if self.is_performance | |
+ else UseCaseKey.RELEASE_HEALTH, | |
+ include_meta=True, | |
+ ) | |
+ except Exception as err: | |
+ raise IncompatibleMetricsQuery(err) | |
+ with sentry_sdk.start_span(op="metric_layer", description="transform_results"): | |
+ # series does some strange stuff to the clickhouse response, turn it back so we can handle it | |
+ metric_layer_result: Any = { | |
+ "data": [], | |
+ "meta": metrics_data["meta"], | |
+ } | |
+ for group in metrics_data["groups"]: | |
+ data = group["by"] | |
+ data.update(group["totals"]) | |
+ metric_layer_result["data"].append(data) | |
+ for meta in metric_layer_result["meta"]: | |
+ if data[meta["name"]] is None: | |
+ data[meta["name"]] = self.get_default_value(meta["type"]) | |
+ return metric_layer_result | |
self.validate_having_clause() | |
self.validate_orderby_clause() | |
@@ -759,6 +758,8 @@ class MetricsQueryBuilder(QueryBuilder): | |
class AlertMetricsQueryBuilder(MetricsQueryBuilder): | |
+ is_alerts_query = True | |
+ | |
def __init__( | |
self, | |
*args: Any, | |
@@ -774,50 +775,33 @@ class AlertMetricsQueryBuilder(MetricsQueryBuilder): | |
def resolve_granularity(self) -> Granularity: | |
return Granularity(self._granularity) | |
- def _get_snql_using_metrics_layer(self, snuba_request: Request) -> Request: | |
- # We use directly the query builder which is not a good practice, considering that the metrics layer | |
- # should hide snql generation. | |
- from sentry.snuba.metrics import SnubaQueryBuilder | |
- from sentry.snuba.metrics.mqb_query_transformer import transform_mqb_query_to_metrics_query | |
- | |
- snuba_queries, _ = SnubaQueryBuilder( | |
- projects=self.params.projects, | |
- metrics_query=transform_mqb_query_to_metrics_query( | |
- snuba_request.query, is_alerts_query=True | |
- ), | |
- use_case_id=UseCaseKey.PERFORMANCE | |
- if self.is_performance | |
- else UseCaseKey.RELEASE_HEALTH, | |
- ).get_snuba_queries() | |
- | |
- if len(snuba_queries) == 0 or len(snuba_queries) > 1: | |
- raise NotImplementedError( | |
- "get_snql_query cannot be implemented for MetricsQueryBuilder" | |
- ) | |
- | |
- # We take only the first query, supposing a single query is generated. | |
- entity = list(snuba_queries.keys())[0] | |
- snuba_request.query = snuba_queries[entity]["totals"] | |
- | |
- return snuba_request | |
- | |
- def run_query(self, referrer: str, use_cache: bool = False) -> Any: | |
- if self.use_metrics_layer: | |
- # We have to copy the entire code of the run query here, because of how the get_snql_query() method | |
- # behaves. The get_snql_query() of MetricsQueryBuilder returns a snql query that is understood by the mqb | |
- # transformer. If we were to call get_snql_query() of this class, we would already get snql generated | |
- # by the metrics layer, which is not understood by the transformer. | |
- snuba_query = super().get_snql_query().query | |
- return self._run_query_with_metrics_layer(query=snuba_query, is_alerts_query=True) | |
- | |
- return super().run_query(referrer, use_cache) | |
- | |
def get_snql_query(self) -> Request: | |
request = super().get_snql_query() | |
if self.use_metrics_layer: | |
- # Generate through metrics layer | |
- request = self._get_snql_using_metrics_layer(request) | |
+ # We use directly the query builder which is not a good practice, considering that the metrics layer | |
+ # should hide snql generation. | |
+ from sentry.snuba.metrics import SnubaQueryBuilder | |
+ from sentry.snuba.metrics.mqb_query_transformer import transform_mqb_query_to_metrics_query | |
+ | |
+ snuba_queries, _ = SnubaQueryBuilder( | |
+ projects=self.params.projects, | |
+ metrics_query=transform_mqb_query_to_metrics_query( | |
+ request.query, is_alerts_query=True | |
+ ), | |
+ use_case_id=UseCaseKey.PERFORMANCE | |
+ if self.is_performance | |
+ else UseCaseKey.RELEASE_HEALTH, | |
+ ).get_snuba_queries() | |
+ | |
+ if len(snuba_queries) == 0 or len(snuba_queries) > 1: | |
+ raise NotImplementedError( | |
+ "get_snql_query cannot be implemented for MetricsQueryBuilder" | |
+ ) | |
+ | |
+ # We take only the first query, supposing a single query is generated. | |
+ entity = list(snuba_queries.keys())[0] | |
+ request.query = snuba_queries[entity]["totals"] | |
return request | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment