Skip to content

Commit 877b464

Browse files
authored
fix: Renormalize once (#12991)
1 parent e4877f5 commit 877b464

File tree

5 files changed

+62
-4
lines changed

5 files changed

+62
-4
lines changed

src/sentry/event_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
)
3737
from sentry.interfaces.base import get_interface
3838
from sentry.models import (
39-
Activity, Environment, Event, EventError, EventMapping, EventUser, Group,
39+
Activity, Environment, Event, EventDict, EventError, EventMapping, EventUser, Group,
4040
GroupEnvironment, GroupHash, GroupLink, GroupRelease, GroupResolution, GroupStatus,
4141
Project, Release, ReleaseEnvironment, ReleaseProject,
4242
ReleaseProjectEnvironment, UserReport, Organization,
@@ -585,7 +585,7 @@ def _get_event_instance(self, project_id=None):
585585
return Event(
586586
project_id=project_id or self._project.id,
587587
event_id=event_id,
588-
data=data,
588+
data=EventDict(data, skip_renormalization=True),
589589
time_spent=time_spent,
590590
datetime=date,
591591
platform=platform

src/sentry/models/event.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,17 @@ class EventDict(CanonicalKeyDict):
6464
"""
6565

6666
def __init__(self, data, skip_renormalization=False, **kwargs):
67-
if not skip_renormalization and not isinstance(data, EventDict):
67+
is_renormalized = (
68+
isinstance(data, EventDict) or
69+
(isinstance(data, NodeData) and isinstance(data.data, EventDict))
70+
)
71+
72+
with configure_scope() as scope:
73+
scope.set_tag("rust.is_renormalized", is_renormalized)
74+
scope.set_tag("rust.skip_renormalization", skip_renormalization)
75+
scope.set_tag("rust.renormalized", "null")
76+
77+
if not skip_renormalization and not is_renormalized:
6878
rust_renormalized = _should_skip_to_python(data.get('event_id'))
6979
if rust_renormalized:
7080
normalizer = StoreNormalizer(is_renormalize=True)

src/sentry/tasks/post_process.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from django.conf import settings
1515

1616
from sentry import features
17+
from sentry.models import EventDict
1718
from sentry.utils import snuba
1819
from sentry.utils.cache import cache
1920
from sentry.exceptions import PluginError
@@ -113,6 +114,10 @@ def post_process_group(event, is_new, is_regression, is_sample, is_new_group_env
113114
from sentry.rules.processor import RuleProcessor
114115
from sentry.tasks.servicehooks import process_service_hook
115116

117+
# Re-bind node data to avoid renormalization. We only want to
118+
# renormalize when loading old data from the database.
119+
event.data = EventDict(event.data, skip_renormalization=True)
120+
116121
# Re-bind Group since we're pickling the whole Event object
117122
# which may contain a stale Group.
118123
event.group, _ = get_group_with_redirect(event.group_id)

src/sentry/utils/pytest/fixtures.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ def factories():
149149
return Factories
150150

151151

152+
@pytest.fixture
153+
def task_runner():
154+
from sentry.testutils.helpers.task_runner import TaskRunner
155+
return TaskRunner
156+
157+
152158
@pytest.fixture(scope='function')
153159
def session():
154160
return factories.create_session()

tests/sentry/models/test_event.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from __future__ import absolute_import
22

3+
import pytest
34
import pickle
45

56
from sentry.models import Environment
6-
from sentry.testutils import TestCase
77
from sentry.db.models.fields.node import NodeData
88
from sentry.event_manager import EventManager
9+
from sentry.testutils import TestCase
910

1011

1112
class EventTest(TestCase):
@@ -162,6 +163,42 @@ def test_ip_address(self):
162163
assert event.ip_address is None
163164

164165

166+
@pytest.mark.django_db
167+
def test_renormalization(monkeypatch, factories, task_runner, default_project):
168+
from semaphore.processing import StoreNormalizer
169+
170+
old_normalize = StoreNormalizer.normalize_event
171+
normalize_mock_calls = []
172+
173+
def normalize(*args, **kwargs):
174+
normalize_mock_calls.append(1)
175+
return old_normalize(*args, **kwargs)
176+
177+
monkeypatch.setattr('semaphore.processing.StoreNormalizer.normalize_event',
178+
normalize)
179+
180+
sample_mock_calls = []
181+
182+
def sample(*args, **kwargs):
183+
sample_mock_calls.append(1)
184+
return False
185+
186+
with task_runner():
187+
factories.store_event(
188+
data={
189+
'event_id': 'a' * 32,
190+
'environment': 'production',
191+
},
192+
project_id=default_project.id
193+
)
194+
195+
# Assert we only renormalize this once. If this assertion fails it's likely
196+
# that you will encounter severe performance issues during event processing
197+
# or postprocessing.
198+
assert len(normalize_mock_calls) == 1
199+
assert len(sample_mock_calls) == 0
200+
201+
165202
class EventGetLegacyMessageTest(TestCase):
166203
def test_message(self):
167204
event = self.create_event(message='foo bar')

0 commit comments

Comments
 (0)