Skip to content

Commit 744c336

Browse files
committed
fix(taskworker) Remove pickle usage from sentryapps task
The `event` parameter of process_service_hook requires pickle. By generating the payload before spawning a task, we don't have to use pickle. Refs SENTRY-3V47
1 parent 289d05a commit 744c336

File tree

3 files changed

+53
-18
lines changed

3 files changed

+53
-18
lines changed

src/sentry/sentry_apps/tasks/service_hooks.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
from time import time
3+
from typing import Any
34

45
from sentry.api.serializers import serialize
56
from sentry.http import safe_urlopen
@@ -40,16 +41,24 @@ def get_payload_v0(event):
4041
taskworker_config=TaskworkerConfig(namespace=sentryapp_tasks, retry=Retry(times=3)),
4142
)
4243
@retry
43-
def process_service_hook(servicehook_id, event, **kwargs):
44+
def process_service_hook(
45+
servicehook_id: int,
46+
event: Any,
47+
payload: str | None = None,
48+
project_id: int | None = None,
49+
**kwargs,
50+
):
4451
try:
4552
servicehook = ServiceHook.objects.get(id=servicehook_id)
4653
except ServiceHook.DoesNotExist:
4754
return
4855

49-
if servicehook.version == 0:
50-
payload = get_payload_v0(event)
51-
else:
52-
raise NotImplementedError
56+
project_id = project_id or event.project_id
57+
if not payload:
58+
if servicehook.version == 0:
59+
payload = json.dumps(get_payload_v0(event))
60+
else:
61+
raise NotImplementedError
5362

5463
from sentry import tsdb
5564

@@ -59,10 +68,8 @@ def process_service_hook(servicehook_id, event, **kwargs):
5968
"Content-Type": "application/json",
6069
"X-ServiceHook-Timestamp": str(int(time())),
6170
"X-ServiceHook-GUID": servicehook.guid,
62-
"X-ServiceHook-Signature": servicehook.build_signature(json.dumps(payload)),
71+
"X-ServiceHook-Signature": servicehook.build_signature(payload),
6372
}
6473

65-
safe_urlopen(
66-
url=servicehook.url, data=json.dumps(payload), headers=headers, timeout=5, verify_ssl=False
67-
)
68-
logger.info("service_hook.success", extra={"project_id": event.project_id})
74+
safe_urlopen(url=servicehook.url, data=payload, headers=headers, timeout=5, verify_ssl=False)
75+
logger.info("service_hook.success", extra={"project_id": project_id})

src/sentry/tasks/post_process.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class PostProcessJob(TypedDict, total=False):
7272
has_escalated: bool
7373

7474

75-
def _get_service_hooks(project_id):
75+
def _get_service_hooks(project_id: int) -> list[tuple[int, list[str]]]:
7676
from sentry.sentry_apps.models.servicehook import ServiceHook
7777

7878
cache_key = f"servicehooks:1:{project_id}"
@@ -1180,7 +1180,7 @@ def process_service_hooks(job: PostProcessJob) -> None:
11801180
if job["is_reprocessed"]:
11811181
return
11821182

1183-
from sentry.sentry_apps.tasks.service_hooks import process_service_hook
1183+
from sentry.sentry_apps.tasks.service_hooks import get_payload_v0, process_service_hook
11841184

11851185
event, has_alert = job["event"], job["has_alert"]
11861186

@@ -1189,10 +1189,17 @@ def process_service_hooks(job: PostProcessJob) -> None:
11891189
if has_alert:
11901190
allowed_events.add("event.alert")
11911191

1192-
if allowed_events:
1193-
for servicehook_id, events in _get_service_hooks(project_id=event.project_id):
1194-
if any(e in allowed_events for e in events):
1195-
process_service_hook.delay(servicehook_id=servicehook_id, event=event)
1192+
# TODO: when we have multiple service hook versions, this will need to change.
1193+
payload = json.dumps(get_payload_v0(event))
1194+
1195+
for servicehook_id, events in _get_service_hooks(project_id=event.project_id):
1196+
if any(e in allowed_events for e in events):
1197+
process_service_hook.delay(
1198+
servicehook_id=servicehook_id,
1199+
project_id=event.project_id,
1200+
event=event,
1201+
payload=payload,
1202+
)
11961203

11971204

11981205
def process_resource_change_bounds(job: PostProcessJob) -> None:

tests/sentry/tasks/test_post_process.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ def __eq__(self, other):
9999
return matching_id
100100

101101

102+
class ServiceHookPayloadMatcher:
103+
def __init__(self, event: Event):
104+
self.event = event
105+
106+
def __eq__(self, other: str) -> bool:
107+
assert isinstance(other, str), "other should be a string"
108+
payload = json.loads(other)
109+
assert payload["event"]["id"] == self.event.event_id
110+
assert payload["group"]["id"] == str(self.event.group.id)
111+
assert "url" in payload["group"]
112+
assert "tags" in payload["event"]
113+
assert "project" in payload
114+
return True
115+
116+
102117
class BasePostProgressGroupMixin(BaseTestCase, metaclass=abc.ABCMeta):
103118
@abc.abstractmethod
104119
def create_event(self, data, project_id, assert_no_errors=True):
@@ -518,7 +533,10 @@ def test_service_hook_fires_on_new_event(self, mock_process_service_hook):
518533
)
519534

520535
mock_process_service_hook.delay.assert_called_once_with(
521-
servicehook_id=hook.id, event=EventMatcher(event)
536+
servicehook_id=hook.id,
537+
project_id=self.project.id,
538+
event=EventMatcher(event),
539+
payload=ServiceHookPayloadMatcher(event),
522540
)
523541

524542
@patch("sentry.sentry_apps.tasks.service_hooks.process_service_hook")
@@ -547,7 +565,10 @@ def test_service_hook_fires_on_alert(self, mock_processor, mock_process_service_
547565
)
548566

549567
mock_process_service_hook.delay.assert_called_once_with(
550-
servicehook_id=hook.id, event=EventMatcher(event)
568+
servicehook_id=hook.id,
569+
project_id=self.project.id,
570+
event=EventMatcher(event),
571+
payload=ServiceHookPayloadMatcher(event),
551572
)
552573

553574
@patch("sentry.sentry_apps.tasks.service_hooks.process_service_hook")

0 commit comments

Comments
 (0)