Skip to content

Commit 4db9973

Browse files
cursoragentarmenzg
andcommitted
fix(eventstore): Add EAP double-read validation to nodestore optimization path
The nodestore optimization path in __get_events was bypassing the EAP double-read comparison entirely, causing validation metrics to be incomplete for callsites like UserReportSerializer.get_attrs and Group.filter_by_event_id that pass eap_conditions. This fix adds the same EAP validation logic to the nodestore path that was already present in the normal Snuba query path, ensuring consistent comparison coverage across all code paths. Co-authored-by: Armen Zambrano G. <armenzg@users.noreply.github.com>
1 parent 2c5b26e commit 4db9973

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/sentry/services/eventstore/snuba/backend.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,58 @@ def __get_events(
352352
for event in events:
353353
node_data = nodestore_dict[(event.event_id, event.project_id)]
354354
event.data.bind_data(node_data)
355+
356+
callsite = "eventstore.backend.get_events"
357+
if (
358+
eap_conditions is not None
359+
and tenant_ids
360+
and "organization_id" in tenant_ids
361+
and EAPOccurrencesComparator.should_check_experiment(callsite)
362+
):
363+
occurrence_category = (
364+
OccurrenceCategory.ISSUE_PLATFORM
365+
if dataset == Dataset.IssuePlatform
366+
else OccurrenceCategory.ERROR
367+
)
368+
eap_results = self._get_events_eap(
369+
eap_conditions=eap_conditions,
370+
project_ids=filter.project_ids or [],
371+
organization_id=tenant_ids["organization_id"],
372+
occurrence_category=occurrence_category,
373+
orderby=orderby,
374+
limit=limit,
375+
offset=offset,
376+
referrer=referrer,
377+
start=filter.start,
378+
end=filter.end,
379+
group_ids=filter.group_ids,
380+
)
381+
control_data = {(e.event_id, e.group_id) for e in events}
382+
experimental_data = (
383+
{(row["id"], row["group_id"]) for row in eap_results}
384+
if eap_results is not None
385+
else set()
386+
)
387+
EAPOccurrencesComparator.check_and_choose(
388+
control_data=control_data,
389+
experimental_data=experimental_data,
390+
callsite=callsite,
391+
is_experimental_data_a_null_result=eap_results is None,
392+
reasonable_match_comparator=lambda ctl, exp: exp.issubset(ctl),
393+
debug_context={
394+
"project_ids": list(filter.project_ids)
395+
if filter.project_ids
396+
else [],
397+
"group_ids": list(filter.group_ids) if filter.group_ids else [],
398+
"dataset": dataset.value,
399+
"limit": limit,
400+
"offset": offset,
401+
"referrer": referrer,
402+
"control_count": len(events),
403+
"experimental_count": len(experimental_data),
404+
},
405+
)
406+
355407
return events
356408

357409
return []

0 commit comments

Comments
 (0)