From 80ecad46cfbad46f5b79171f3d1793613d5dd808 Mon Sep 17 00:00:00 2001 From: Kev Date: Fri, 23 May 2025 13:48:04 -0400 Subject: [PATCH] fix(ourlogs): Allow multiple traces Span attribute definitions were updated but not logs, this allows multiple event ids to be sent in a list form as a generic validator. Adds a test. --- src/sentry/search/eap/ourlogs/attributes.py | 4 +-- src/sentry/search/eap/spans/attributes.py | 12 ++----- src/sentry/utils/validators.py | 7 ++++ .../test_organization_events_ourlogs.py | 34 +++++++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/sentry/search/eap/ourlogs/attributes.py b/src/sentry/search/eap/ourlogs/attributes.py index 49045131a618fa..ac8f1112e055fd 100644 --- a/src/sentry/search/eap/ourlogs/attributes.py +++ b/src/sentry/search/eap/ourlogs/attributes.py @@ -10,7 +10,7 @@ simple_sentry_field, ) from sentry.search.eap.common_columns import COMMON_COLUMNS -from sentry.utils.validators import is_event_id +from sentry.utils.validators import is_event_id_or_list OURLOG_ATTRIBUTE_DEFINITIONS = { column.public_alias: column @@ -35,7 +35,7 @@ public_alias="trace", internal_name="sentry.trace_id", search_type="string", - validator=is_event_id, + validator=is_event_id_or_list, ), ResolvedAttribute( public_alias="timestamp", diff --git a/src/sentry/search/eap/spans/attributes.py b/src/sentry/search/eap/spans/attributes.py index 6d35a749a067a1..3a7c0d0a6fcf3c 100644 --- a/src/sentry/search/eap/spans/attributes.py +++ b/src/sentry/search/eap/spans/attributes.py @@ -21,15 +21,7 @@ ) from sentry.search.events.types import SnubaParams from sentry.search.utils import DEVICE_CLASS -from sentry.utils.validators import is_empty_string, is_event_id, is_span_id - - -def validate_event_id(value: str | list[str]) -> bool: - if isinstance(value, list): - return all([is_event_id(item) for item in value]) - else: - return is_event_id(value) - +from sentry.utils.validators import is_empty_string, is_event_id_or_list, is_span_id SPAN_ATTRIBUTE_DEFINITIONS = { column.public_alias: column @@ -125,7 +117,7 @@ def validate_event_id(value: str | list[str]) -> bool: public_alias="trace", internal_name="sentry.trace_id", search_type="string", - validator=validate_event_id, + validator=is_event_id_or_list, ), ResolvedAttribute( public_alias="transaction", diff --git a/src/sentry/utils/validators.py b/src/sentry/utils/validators.py index 736f6745f5fdd0..cfdc3e6e9a6bc7 100644 --- a/src/sentry/utils/validators.py +++ b/src/sentry/utils/validators.py @@ -25,6 +25,13 @@ def is_event_id(value): return normalize_event_id(value) is not None +def is_event_id_or_list(value): + if isinstance(value, list): + return all(is_event_id(item) for item in value) + else: + return is_event_id(value) + + def is_span_id(value): return bool(HEXADECIMAL_16_DIGITS.search(force_str(value))) diff --git a/tests/snuba/api/endpoints/test_organization_events_ourlogs.py b/tests/snuba/api/endpoints/test_organization_events_ourlogs.py index d7019215db0da6..46430efc8cf33b 100644 --- a/tests/snuba/api/endpoints/test_organization_events_ourlogs.py +++ b/tests/snuba/api/endpoints/test_organization_events_ourlogs.py @@ -183,3 +183,37 @@ def test_project_slug_field(self): assert data[0]["project"] == self.project.slug assert meta["dataset"] == self.dataset + + def test_trace_id_list_filter(self): + trace_id_1 = "1" * 32 + trace_id_2 = "2" * 32 + logs = [ + self.create_ourlog( + {"body": "foo", "trace_id": trace_id_1}, + timestamp=self.ten_mins_ago, + ), + self.create_ourlog( + {"body": "bar", "trace_id": trace_id_2}, + timestamp=self.ten_mins_ago, + ), + ] + self.store_ourlogs(logs) + response = self.do_request( + { + "field": ["message", "trace"], + "query": f"trace:[{trace_id_1},{trace_id_2}]", + "orderby": "message", + "project": self.project.id, + "dataset": self.dataset, + } + ) + + assert response.status_code == 200, response.content + data = response.data["data"] + meta = response.data["meta"] + assert len(data) == 2 + assert data == [ + {"message": "bar", "trace": trace_id_2}, + {"message": "foo", "trace": trace_id_1}, + ] + assert meta["dataset"] == self.dataset