Browse Source

feat(spans): Change free text search (#68624)

- This adds a free_text_key to the builders so we can change it per
querybuilder easily
- This changes the free_text_key for indexed spans to `span.description`
William Mak 11 months ago
parent
commit
5ab47708b8

+ 5 - 0
src/sentry/search/events/builder/discover.py

@@ -88,6 +88,7 @@ from sentry.utils.validators import INVALID_ID_DETAILS, INVALID_SPAN_ID, WILDCAR
 class BaseQueryBuilder:
     requires_organization_condition: bool = False
     organization_column: str = "organization.id"
+    free_text_key = "message"
     function_alias_prefix: str | None = None
     spans_metrics_builder = False
     entity: Entity | None = None
@@ -201,6 +202,10 @@ class BaseQueryBuilder:
             self.builder_config = QueryBuilderConfig()
         else:
             self.builder_config = config
+        if self.builder_config.parser_config_overrides is None:
+            self.builder_config.parser_config_overrides = {}
+        self.builder_config.parser_config_overrides["free_text_key"] = self.free_text_key
+
         self.dataset = dataset
 
         # filter params is the older style params, shouldn't be used anymore

+ 1 - 0
src/sentry/search/events/builder/spans_indexed.py

@@ -6,6 +6,7 @@ from sentry.search.events.types import SelectType
 
 class SpansIndexedQueryBuilder(QueryBuilder):
     requires_organization_condition = False
+    free_text_key = "span.description"
 
     def get_field_type(self, field: str) -> str | None:
         if field in self.meta_resolver_map:

+ 2 - 19
src/sentry/search/events/builder/spans_metrics.py

@@ -1,5 +1,3 @@
-from typing import Any
-
 from snuba_sdk import Condition, Granularity
 
 from sentry.search.events import constants
@@ -8,29 +6,14 @@ from sentry.search.events.builder import (
     TimeseriesMetricQueryBuilder,
     TopMetricsQueryBuilder,
 )
-from sentry.search.events.types import QueryBuilderConfig, SelectType
+from sentry.search.events.types import SelectType
 
 
 class SpansMetricsQueryBuilder(MetricsQueryBuilder):
     requires_organization_condition = True
     spans_metrics_builder = True
     has_transaction = False
-
-    def __init__(
-        self,
-        *args: Any,
-        **kwargs: Any,
-    ):
-        config = kwargs.pop("config", None)
-        if config is None:
-            config = QueryBuilderConfig()
-        parser_config_overrides = (
-            config.parser_config_overrides if config.parser_config_overrides else {}
-        )
-        parser_config_overrides["free_text_key"] = "span.description"
-        config.parser_config_overrides = parser_config_overrides
-        kwargs["config"] = config
-        super().__init__(*args, **kwargs)
+    free_text_key = "span.description"
 
     @property
     def use_default_tags(self) -> bool:

+ 2 - 1
tests/sentry/search/events/builder/test_span_metrics.py

@@ -8,6 +8,7 @@ from sentry.search.events.builder import (
     SpansMetricsQueryBuilder,
     TimeseriesSpansMetricsQueryBuilder,
 )
+from sentry.search.events.types import ParamsType
 from sentry.testutils.cases import MetricsEnhancedPerformanceTestCase
 
 pytestmark = pytest.mark.sentry_metrics
@@ -231,7 +232,7 @@ class MetricQueryBuilderTest(MetricsEnhancedPerformanceTestCase):
 
 class TimeseriesMetricQueryBuilder(MetricsEnhancedPerformanceTestCase):
     def test_split_granularity(self):
-        params = {
+        params: ParamsType = {
             "organization_id": self.organization.id,
             "project_id": [self.project.id],
             "start": datetime.datetime(2015, 5, 18, 23, 3, 0, tzinfo=timezone.utc),

+ 21 - 0
tests/sentry/search/events/builder/test_spans_indexed.py

@@ -91,3 +91,24 @@ def test_span_duration_where(params, condition, op, value):
         selected_columns=["count"],
     )
     assert Condition(span_duration, op, value) in builder.where
+
+
+@pytest.mark.parametrize(
+    ["query", "result"],
+    [
+        pytest.param("span.op:params test", Condition(Column("description"), Op.EQ, "test")),
+        pytest.param("testing", Condition(Column("description"), Op.EQ, "testing")),
+        pytest.param(
+            "span.description:test1 test2", Condition(Column("description"), Op.EQ, "test2")
+        ),
+    ],
+)
+@django_db_all
+def test_free_text_search(params, query, result):
+    builder = SpansIndexedQueryBuilder(
+        Dataset.SpansIndexed,
+        params,
+        query=query,
+        selected_columns=["count"],
+    )
+    assert result in builder.where