Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/sentry/hybridcloud/tasks/deliver_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,20 +370,42 @@ def _discard_stale_mailbox_payloads(payload: WebhookPayload) -> None:
)


def _get_github_delivery_time_tags(payload: WebhookPayload) -> dict[str, str]:
"""Extract GitHub event type and action from payload for delivery_time_ms metric tags."""
if payload.provider != "github":
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment we only care about GitHub for code reviews.

return {}
tags: dict[str, str] = {}
try:
headers = orjson.loads(payload.request_headers)
except orjson.JSONDecodeError:
return {}
if isinstance(headers, dict):
for key, value in headers.items():
if key.upper() == "X-GITHUB-EVENT" and isinstance(value, str) and value:
tags["github_event_type"] = value
break
try:
body = orjson.loads(payload.request_body)
except orjson.JSONDecodeError:
return tags
if isinstance(body, dict):
action = body.get("action")
if isinstance(action, str) and action:
tags["github_action"] = action
return tags


def _record_delivery_time_metrics(payload: WebhookPayload) -> None:
"""Record delivery time metrics for a successfully delivered webhook payload."""
exclude_mailboxes = set(
options.get("hybridcloud.deliver_webhooks.delivery_time_exclude_mailboxes") or ()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orthogonal: We don't need this flag anymore.

)
if payload.mailbox_name in exclude_mailboxes:
return
duration = timezone.now() - payload.date_added
region_sent_to = (
payload.region_name
if payload.destination_type == DestinationType.SENTRY_REGION
else "codecov"
)
tags = {"region_sent_to": region_sent_to}
if options.get("hybridcloud.deliver_webhooks.delivery_time_include_github_tags"):
tags |= _get_github_delivery_time_tags(payload)
metrics.distribution(
"hybridcloud.deliver_webhooks.delivery_time_ms",
# e.g. 0.123 seconds → 123 milliseconds
Expand Down
8 changes: 3 additions & 5 deletions src/sentry/options/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -2496,12 +2496,10 @@
flags=FLAG_AUTOMATOR_MODIFIABLE,
)
register(
"hybridcloud.deliver_webhooks.delivery_time_exclude_mailboxes",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed anymore.

type=Sequence,
default=[],
flags=FLAG_ALLOW_EMPTY | FLAG_AUTOMATOR_MODIFIABLE,
"hybridcloud.deliver_webhooks.delivery_time_include_github_tags",
default=False,
flags=FLAG_AUTOMATOR_MODIFIABLE,
)

# Break glass controls
register(
"hybrid_cloud.rpc.disabled-service-methods",
Expand Down
70 changes: 50 additions & 20 deletions tests/sentry/hybridcloud/tasks/test_deliver_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any
from unittest.mock import MagicMock, PropertyMock, patch

import orjson
import pytest
import responses
from django.test import override_settings
Expand Down Expand Up @@ -1039,13 +1040,9 @@ def test_delivery_time_metrics_codecov_region_sent_to(self, mock_metrics: MagicM

@responses.activate
@override_regions(region_config)
@override_options(
{"hybridcloud.deliver_webhooks.delivery_time_exclude_mailboxes": ["github:123"]}
)
@override_options({"hybridcloud.deliver_webhooks.delivery_time_include_github_tags": True})
@patch("sentry.hybridcloud.tasks.deliver_webhooks.metrics")
def test_delivery_time_metrics_excluded_mailbox_does_not_record(
self, mock_metrics: MagicMock
) -> None:
def test_delivery_time_metrics_github_event_and_action(self, mock_metrics: MagicMock) -> None:
responses.add(
responses.POST,
"http://us.testserver/extensions/github/webhook/",
Expand All @@ -1055,6 +1052,11 @@ def test_delivery_time_metrics_excluded_mailbox_does_not_record(
webhook = self.create_webhook_payload(
mailbox_name="github:123",
region_name="us",
provider="github",
request_headers=orjson.dumps(
{"X-GitHub-Event": "pull_request", "Content-Type": "application/json"}
).decode(),
request_body=orjson.dumps({"action": "opened", "repository": {}}).decode(),
)
drain_mailbox(webhook.id)

Expand All @@ -1063,34 +1065,59 @@ def test_delivery_time_metrics_excluded_mailbox_does_not_record(
for c in mock_metrics.distribution.call_args_list
if c[0][0] == "hybridcloud.deliver_webhooks.delivery_time_ms"
]
assert len(delivery_time_ms_calls) == 0
assert len(delivery_time_ms_calls) == 1
tags = delivery_time_ms_calls[0][1].get("tags", {})
assert tags.get("region_sent_to") == "us"
assert tags.get("github_event_type") == "pull_request"
assert tags.get("github_action") == "opened"

incr_calls = [
@responses.activate
@override_regions(region_config)
@override_options({"hybridcloud.deliver_webhooks.delivery_time_include_github_tags": True})
@patch("sentry.hybridcloud.tasks.deliver_webhooks.metrics")
def test_delivery_time_metrics_github_event_only(self, mock_metrics: MagicMock) -> None:
responses.add(
responses.POST,
"http://us.testserver/extensions/github/webhook/",
status=200,
body="",
)
webhook = self.create_webhook_payload(
mailbox_name="github:123",
region_name="us",
provider="github",
request_headers=orjson.dumps(
{"X-GitHub-Event": "push", "Content-Type": "application/json"}
).decode(),
request_body=orjson.dumps({"repository": {}}).decode(),
)
drain_mailbox(webhook.id)

delivery_time_ms_calls = [
c
for c in mock_metrics.incr.call_args_list
if c[0][0] == "hybridcloud.deliver_webhooks.delivery"
for c in mock_metrics.distribution.call_args_list
if c[0][0] == "hybridcloud.deliver_webhooks.delivery_time_ms"
]
assert len(incr_calls) == 1
assert incr_calls[0][1].get("tags", {}).get("outcome") == "ok"
assert len(delivery_time_ms_calls) == 1
tags = delivery_time_ms_calls[0][1].get("tags", {})
assert tags.get("region_sent_to") == "us"
assert tags.get("github_event_type") == "push"
assert "github_action" not in tags

@responses.activate
@override_regions(region_config)
@override_options(
{"hybridcloud.deliver_webhooks.delivery_time_exclude_mailboxes": ["other:mailbox"]}
)
@patch("sentry.hybridcloud.tasks.deliver_webhooks.metrics")
def test_delivery_time_metrics_non_excluded_mailbox_still_records(
self, mock_metrics: MagicMock
) -> None:
def test_delivery_time_metrics_non_github_no_github_tags(self, mock_metrics: MagicMock) -> None:
responses.add(
responses.POST,
"http://us.testserver/extensions/github/webhook/",
status=200,
body="",
)
webhook = self.create_webhook_payload(
mailbox_name="github:123",
mailbox_name="stripe:123",
region_name="us",
provider="stripe",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the provider is stripe we will not have the extra two tags.

)
drain_mailbox(webhook.id)

Expand All @@ -1100,7 +1127,10 @@ def test_delivery_time_metrics_non_excluded_mailbox_still_records(
if c[0][0] == "hybridcloud.deliver_webhooks.delivery_time_ms"
]
assert len(delivery_time_ms_calls) == 1
assert delivery_time_ms_calls[0][1].get("tags", {}).get("region_sent_to") == "us"
tags = delivery_time_ms_calls[0][1].get("tags", {})
assert tags.get("region_sent_to") == "us"
assert "github_event_type" not in tags
assert "github_action" not in tags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test doesn't enable feature flag, never exercises provider filtering

Low Severity

test_delivery_time_metrics_non_github_no_github_tags is missing the @override_options({"hybridcloud.deliver_webhooks.delivery_time_include_github_tags": True}) decorator. Since the option defaults to False, _get_github_delivery_time_tags is never called, and the assertions that github_event_type and github_action are absent pass trivially. The test doesn't actually validate that non-GitHub providers are filtered out by the provider check — a bug in that check would go undetected.

Fix in Cursor Fix in Web



@control_silo_test
Expand Down
Loading