Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e6c0196
feat(browser-reports): Validate both browser report formats (#93917)
armenzg Jun 20, 2025
ba199fa
fix(insights): adds referrer to Insights charts create alerts url (#9…
edwardgou-sentry Jun 20, 2025
668229d
Revert "chore(autofix): Change default automation tuning from 'off' t…
getsentry-bot Jun 20, 2025
a6e22c7
fix(aci): Use contextual logger in workflow processor (#93947)
kcons Jun 20, 2025
4549d79
fix(taskworker) Increase deadlines for webhook delivery (#93941)
markstory Jun 20, 2025
1a81517
fix(ourlogs): Fix top events for logs (#93939)
colin-sentry Jun 20, 2025
37375d9
feat(aci): Set ownership on detector (#93745)
scttcper Jun 20, 2025
976bb0b
Update RightMask component background gradient (#93933)
JonasBa Jun 20, 2025
d088de3
button: fix transition (#93934)
JonasBa Jun 20, 2025
8a179d9
fix(migrations): Patch broken saved search migrations (#93944)
malwilley Jun 20, 2025
4f92a94
fix(replay): Fix summaries not loading due to using wrong `project_id…
billyvg Jun 20, 2025
a37f99f
feat(replay): Add analytics to timeline zoom buttons (#93910)
billyvg Jun 20, 2025
38d4d58
ref(profiling): Move flamegraphFrameFilter types around for tsgo (#93…
scttcper Jun 20, 2025
78d346e
feat(devservices): Add tracing mode (#93759)
hubertdeng123 Jun 20, 2025
5cc91e0
feat(feedback): frontend to display summary (#93567)
vishnupsatish Jun 20, 2025
084b63a
fix(aci): Ensure slow conditions are consistent (#93895)
kcons Jun 20, 2025
b364405
chore(issues): Remove regex parameterization experiment (#93958)
mrduncan Jun 20, 2025
8167cc5
ref(replay): include error context in breadcrumb summary (#93669)
michellewzhang Jun 20, 2025
5d66a4f
ref(feedback): better summarization prompt (#93962)
vishnupsatish Jun 20, 2025
fd4ab7b
✨ feat(scm): add environment infomation to suspect commit prs (#93025)
iamrajjoshi Jun 20, 2025
31c51d5
flex: cleanup Flex* custom styling in favor of Flex primitive (#93809)
JonasBa Jun 20, 2025
b4d3000
fix(taskworker) Extend deadlines for check_auth (#93961)
markstory Jun 20, 2025
02695f9
ref(issues): Remove redundant Type row from Event Grouping Informatio…
nora-shap Jun 20, 2025
4c997de
ref(dashboards): add a new table widget visualization component (#93902)
lzhao-sentry Jun 20, 2025
2e992ba
feat(detectors): Add noise config to DB Query Injection Issue Type (#…
roggenkemper Jun 20, 2025
b3f40e5
fix(aci): Fix accidental over-logging (#93971)
kcons Jun 20, 2025
de377a6
feat(trace-eap-waterfall): Hiding some attrs (#93964)
Abdkhan14 Jun 20, 2025
786861a
feat(preprod): Add analytics to the assemble endpoint (#93871)
trevor-e Jun 20, 2025
c05a0c6
ref(explore): Visualize should only have 1 y axis (#93938)
Zylphrex Jun 20, 2025
9f84049
ref(trace-items): Pull useGetTraceItemAttributeKeys into hook (#93739)
Zylphrex Jun 20, 2025
c9fee3f
chore(issues): Remove traceparent experiment (#93942)
mrduncan Jun 20, 2025
ea188e2
fix(replay): Add handling for null max_segment_id (#93989)
cmanallen Jun 20, 2025
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
47 changes: 47 additions & 0 deletions devservices/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ x-sentry-service-config:
branch: master
repo_link: https://github.com/getsentry/snuba.git
mode: containerized-profiles
snuba-metrics:
description: Service that provides fast aggregation and query capabilities on top of Clickhouse that includes metrics consumers
remote:
repo_name: snuba
branch: master
repo_link: https://github.com/getsentry/snuba.git
mode: containerized-metrics-dev
relay:
description: Service event forwarding and ingestion service
remote:
Expand Down Expand Up @@ -121,6 +128,15 @@ x-sentry-service-config:
description: Post-process forwarder for transaction events
post-process-forwarder-issue-platform:
description: Post-process forwarder for issue platform events
# Subscription results consumers
eap-spans-subscription-results:
description: Kafka consumer for processing subscription results for spans
subscription-results-eap-items:
description: Kafka consumer for processing subscription results for eap items
metrics-subscription-results:
description: Kafka consumer for processing subscription results for metrics
generic-metrics-subscription-results:
description: Kafka consumer for processing subscription results for generic metrics
# Uptime monitoring
uptime-results:
description: Kafka consumer for uptime monitoring results
Expand All @@ -138,6 +154,29 @@ x-sentry-service-config:
rabbitmq: [postgres, snuba, rabbitmq, spotlight]
symbolicator: [postgres, snuba, symbolicator, spotlight]
memcached: [postgres, snuba, memcached, spotlight]
tracing:
[
postgres,
snuba-metrics,
relay,
spotlight,
ingest-events,
ingest-transactions,
ingest-metrics,
ingest-generic-metrics,
billing-metrics-consumer,
post-process-forwarder-errors,
post-process-forwarder-transactions,
post-process-forwarder-issue-platform,
eap-spans-subscription-results,
subscription-results-eap-items,
metrics-subscription-results,
generic-metrics-subscription-results,
process-spans,
ingest-occurrences,
process-segments,
worker,
]
crons:
[
postgres,
Expand Down Expand Up @@ -283,6 +322,14 @@ x-programs:
command: sentry run consumer post-process-forwarder-issue-platform --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
ingest-feedback-events:
command: sentry run consumer ingest-feedback-events --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
eap-spans-subscription-results:
command: sentry run consumer eap-spans-subscription-results --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
subscription-results-eap-items:
command: sentry run consumer subscription-results-eap-items --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
metrics-subscription-results:
command: sentry run consumer metrics-subscription-results --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
generic-metrics-subscription-results:
command: sentry run consumer generic-metrics-subscription-results --consumer-group=sentry-consumer --auto-offset-reset=latest --no-strict-offset-reset
worker:
command: sentry run worker -c 1 --autoreload

Expand Down
2 changes: 1 addition & 1 deletion src/sentry/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ class InsightModules(Enum):
TARGET_SAMPLE_RATE_DEFAULT = 1.0
SAMPLING_MODE_DEFAULT = "organization"
ROLLBACK_ENABLED_DEFAULT = True
DEFAULT_AUTOFIX_AUTOMATION_TUNING_DEFAULT = "low"
DEFAULT_AUTOFIX_AUTOMATION_TUNING_DEFAULT = "off"
DEFAULT_SEER_SCANNER_AUTOMATION_DEFAULT = False
INGEST_THROUGH_TRUSTED_RELAYS_ONLY_DEFAULT = False

Expand Down
8 changes: 5 additions & 3 deletions src/sentry/feedback/usecases/feedback_summaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
def make_input_prompt(
feedbacks,
):
feedbacks_string = "\n".join(f"- {msg}" for msg in feedbacks)
feedbacks_string = "\n------\n".join(feedbacks)
return f"""Instructions:

You are an assistant that summarizes customer feedback. Given a list of customer feedback entries, generate a concise summary of 1-2 sentences that reflects the key themes. Begin the summary with "Users...", for example, "Users say...".
You are an assistant that summarizes customer feedback. Given a list of customer feedback entries, generate a concise summary of 1-2 sentences that reflects the key themes. Begin the summary with "Users...", for example, "Users say...". Don't make overly generic statements like "Users report a variety of issues."

Balance specificity and generalization based on the size of the input based *only* on the themes and topics present in the list of customer feedback entries. Prioritize brevity and clarity and trying to capture what users are saying, over trying to mention random specific topics. Please don't write overly long sentences, you can leave certain things out and the decision to mention specific topics or themes should be proportional to the number of times they appear in the user feedback entries.
Balance specificity and generalization based on the size of the input and based only on the themes and topics present in the list of customer feedback entries. Your goal is to focus on identifying and summarizing broader themes that are mentioned more frequently across different feedback entries. For example, if there are many feedback entries, it makes more sense to prioritize mentioning broader themes that apply to many feedbacks, versus mentioning one or two specific isolated concerns and leaving out others that are just as prevalent.

The summary must be AT MOST 55 words, that is an absolute upper limit, and you must write AT MOST two sentences. You can leave certain things out, and when deciding what topics/themes to mention, make sure it is proportional to the number of times they appear in different customer feedback entries.

User Feedbacks:

Expand Down
18 changes: 3 additions & 15 deletions src/sentry/grouping/parameterization.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"ParameterizationCallableExperiment",
"ParameterizationExperiment",
"ParameterizationRegex",
"ParameterizationRegexExperiment",
"Parameterizer",
"UniqueIdExperiment",
]
Expand Down Expand Up @@ -206,15 +205,6 @@ def run(self, content: str, callback: Callable[[str, int], None]) -> str:
return content


class ParameterizationRegexExperiment(ParameterizationRegex):
def run(
self,
content: str,
callback: Callable[[re.Match[str]], str],
) -> str:
return self.compiled_pattern.sub(callback, content)


class _UniqueId:
# just a namespace for the uniq_id logic, no need to instantiate

Expand Down Expand Up @@ -275,7 +265,7 @@ def replace_uniq_ids_in_str(string: str) -> tuple[str, int]:
)


ParameterizationExperiment = ParameterizationCallableExperiment | ParameterizationRegexExperiment
ParameterizationExperiment = ParameterizationCallableExperiment


class Parameterizer:
Expand Down Expand Up @@ -355,10 +345,8 @@ def _handle_regex_match(match: re.Match[str]) -> str:
for experiment in self._experiments:
if not should_run(experiment.name):
continue
if isinstance(experiment, ParameterizationCallableExperiment):
content = experiment.run(content, _incr_counter)
else:
content = experiment.run(content, _handle_regex_match)

content = experiment.run(content, _incr_counter)

return content

Expand Down
3 changes: 3 additions & 0 deletions src/sentry/hybridcloud/tasks/deliver_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class DeliveryFailed(Exception):
silo_mode=SiloMode.CONTROL,
taskworker_config=TaskworkerConfig(
namespace=hybridcloud_control_tasks,
processing_deadline_duration=30,
),
)
def schedule_webhook_delivery() -> None:
Expand Down Expand Up @@ -157,6 +158,7 @@ def schedule_webhook_delivery() -> None:
silo_mode=SiloMode.CONTROL,
taskworker_config=TaskworkerConfig(
namespace=hybridcloud_control_tasks,
processing_deadline_duration=300,
),
)
def drain_mailbox(payload_id: int) -> None:
Expand Down Expand Up @@ -234,6 +236,7 @@ def drain_mailbox(payload_id: int) -> None:
silo_mode=SiloMode.CONTROL,
taskworker_config=TaskworkerConfig(
namespace=hybridcloud_control_tasks,
processing_deadline_duration=120,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 drain_mailbox_parallel processing_deadline_duration (120s) is shorter than its internal loop timeout (180s) (bug)

drain_mailbox_parallel uses BATCH_SCHEDULE_OFFSET = timedelta(minutes=BACKOFF_INTERVAL) = timedelta(minutes=3) = 180 seconds as its internal deadline. The new processing_deadline_duration=120 tells the taskworker to consider the task failed after only 120 seconds. Because 120 < 180, the taskworker will terminate the task while the task's own loop still believes it has 60 more seconds to deliver webhooks. This can cause partial mailbox drains to be incorrectly treated as failures, potentially causing duplicate retries or message-ordering problems.

By contrast, drain_mailbox (the non-parallel variant) correctly sets processing_deadline_duration=300 > 180s, so only the parallel variant is broken.

💡 Suggestion: Set processing_deadline_duration for drain_mailbox_parallel to at least 180 seconds (matching BATCH_SCHEDULE_OFFSET) plus headroom. Using 300 (matching drain_mailbox) is appropriate:

processing_deadline_duration=300,

Alternatively, define a named constant derived from BACKOFF_INTERVAL to keep the two values in sync automatically.

Suggested change
processing_deadline_duration=120,
processing_deadline_duration=300,
📋 Prompt for AI Agents

In src/sentry/hybridcloud/tasks/deliver_webhooks.py at line 239, the TaskworkerConfig for drain_mailbox_parallel sets processing_deadline_duration=120, but the function's internal while-loop runs for up to BATCH_SCHEDULE_OFFSET (timedelta(minutes=3) = 180 seconds). Since 120 < 180, the taskworker kills the task before the internal deadline fires. Change processing_deadline_duration=120 to processing_deadline_duration=300 (matching the drain_mailbox task) to ensure the taskworker deadline is always longer than the internal loop timeout.

),
)
def drain_mailbox_parallel(payload_id: int) -> None:
Expand Down
6 changes: 2 additions & 4 deletions src/sentry/integrations/github/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,6 @@ def get_open_pr_comment_workflow(self) -> OpenPRCommentWorkflow:

<sub>Did you find this useful? React with a 👍 or 👎</sub>"""

MERGED_PR_SINGLE_ISSUE_TEMPLATE = "- ‼️ **{title}** `{subtitle}` [View Issue]({url})"


class GitHubPRCommentWorkflow(PRCommentWorkflow):
organization_option_key = "sentry:github_pr_bot"
Expand All @@ -405,10 +403,10 @@ def get_comment_body(self, issue_ids: list[int]) -> str:

issue_list = "\n".join(
[
MERGED_PR_SINGLE_ISSUE_TEMPLATE.format(
self.get_merged_pr_single_issue_template(
title=issue.title,
subtitle=self.format_comment_subtitle(issue.culprit or "unknown culprit"),
url=self.format_comment_url(issue.get_absolute_url(), self.referrer_id),
environment=self.get_environment_info(issue),
)
for issue in issues
]
Expand Down
6 changes: 2 additions & 4 deletions src/sentry/integrations/gitlab/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,6 @@ def get_open_pr_comment_workflow(self) -> OpenPRCommentWorkflow:

{issue_list}"""

MERGED_PR_SINGLE_ISSUE_TEMPLATE = "- ‼️ **{title}** `{subtitle}` [View Issue]({url})"


class GitlabPRCommentWorkflow(PRCommentWorkflow):
organization_option_key = "sentry:gitlab_pr_bot"
Expand All @@ -253,10 +251,10 @@ def get_comment_body(self, issue_ids: list[int]) -> str:

issue_list = "\n".join(
[
MERGED_PR_SINGLE_ISSUE_TEMPLATE.format(
self.get_merged_pr_single_issue_template(
title=issue.title,
subtitle=self.format_comment_subtitle(issue.culprit),
url=self.format_comment_url(issue.get_absolute_url(), self.referrer_id),
environment=self.get_environment_info(issue),
)
for issue in issues
]
Expand Down
35 changes: 35 additions & 0 deletions src/sentry/integrations/source_code_management/commit_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class PullRequestFile:
patch: str


ISSUE_TITLE_MAX_LENGTH = 50
MERGED_PR_SINGLE_ISSUE_TEMPLATE = "* ‼️ [**{title}**]({url}){environment}\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Double newline between issue list items due to
in template and
join
(bug)

In commit_context.py line 143, MERGED_PR_SINGLE_ISSUE_TEMPLATE is defined with a trailing :

MERGED_PR_SINGLE_ISSUE_TEMPLATE = "* ‼️ [**{title}**]({url}){environment}
"

Both GitHubPRCommentWorkflow.get_comment_body (github/integration.py line 404) and GitlabPRCommentWorkflow.get_comment_body (gitlab/integration.py line 252) join the rendered items with " ":

issue_list = "
".join([self.get_merged_pr_single_issue_template(...) for issue in issues])

This produces `item1

item2

item3
— a blank line between each item and a trailing blank line after the last one. The old template (MERGED_PR_SINGLE_ISSUE_TEMPLATE = "- ‼️ {title} ...") had no trailing newline, so the "
".join(...)` rendered correctly. The new template breaks the tight bullet list rendering in both GitHub and GitLab PR comment markdown.

💡 Suggestion: Remove the trailing \n from MERGED_PR_SINGLE_ISSUE_TEMPLATE. The join already provides the separator between items; the template should not embed its own trailing newline.

Suggested change
MERGED_PR_SINGLE_ISSUE_TEMPLATE = "* ‼️ [**{title}**]({url}){environment}\n"
MERGED_PR_SINGLE_ISSUE_TEMPLATE = "* ‼️ [**{title}**]({url}){environment}"
📋 Prompt for AI Agents

In src/sentry/integrations/source_code_management/commit_context.py at line 143, remove the trailing \n from MERGED_PR_SINGLE_ISSUE_TEMPLATE. The current value is "* ‼️ [**{title}**]({url}){environment}\n" — change it to "* ‼️ [**{title}**]({url}){environment}". Both GitHub and GitLab callers already join items with "\n", so the embedded trailing newline in the template causes double blank lines between every item in the PR comment output.



class CommitContextIntegration(ABC):
"""
Base class for integrations that include commit context features: suspect commits, suspect PR comments
Expand Down Expand Up @@ -570,6 +574,37 @@ def get_top_5_issues_by_count(
)
return raw_snql_query(request, referrer=self.referrer.value)["data"]

@staticmethod
def _truncate_title(title: str, max_length: int = ISSUE_TITLE_MAX_LENGTH) -> str:
"""Truncate title if it's too long and add ellipsis."""
if len(title) <= max_length:
return title
return title[:max_length].rstrip() + "..."

def get_environment_info(self, issue: Group) -> str:
try:
recommended_event = issue.get_recommended_event()
if recommended_event:
environment = recommended_event.get_environment()
if environment and environment.name:
return f" in `{environment.name}`"
except Exception as e:
# If anything goes wrong, just continue without environment info
logger.info(
"get_environment_info.no-environment",
extra={"issue_id": issue.id, "error": e},
)
return ""
Comment on lines +584 to +597
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 N+1 Snuba and DB queries in get_environment_info called per issue in loop (performance)

get_environment_info(issue) is called inside a list comprehension in both GitHubPRCommentWorkflow.get_comment_body and GitlabPRCommentWorkflow.get_comment_body. For each issue it:

  1. Calls issue.get_recommended_event() → triggers eventstore.backend.get_events_snql() — one Snuba query per issue.
  2. Calls recommended_event.get_environment() → triggers Environment.objects.get(...) — one DB query per issue.

With up to 5 issues passed (from get_top_5_issues_by_count), this results in up to 5 Snuba queries + 5 DB queries fired sequentially in a loop for a single PR comment update.

Relevant code in commit_context.py lines 584–597:

def get_environment_info(self, issue: Group) -> str:
    try:
        recommended_event = issue.get_recommended_event()  # Snuba query
        if recommended_event:
            environment = recommended_event.get_environment()  # DB query
            ...

And caller in github/integration.py lines 404–412:

issue_list = "
".join([
    self.get_merged_pr_single_issue_template(
        ...
        environment=self.get_environment_info(issue),  # called per-issue
    )
    for issue in issues
])

💡 Suggestion: Consider batching the environment lookups before the list comprehension. The recommended event Snuba query could be replaced by reading environment data from the existing Group object (e.g. issue.get_latest_event() with a cached environment tag), or by pre-fetching environment info for all issues in a single query before rendering the list.

📋 Prompt for AI Agents

In src/sentry/integrations/source_code_management/commit_context.py, the get_environment_info method (lines 584-597) fires one Snuba query and one DB query per issue because it's called inside a list comprehension for each issue. Refactor get_comment_body in both github/integration.py (lines 401-415) and gitlab/integration.py (lines 249-263) to pre-compute environment info for all issues before the join. One approach: add a method that accepts a list of issues and returns a dict mapping issue_id to environment string, batching the lookups. Alternatively, use issue.get_tag('environment') from the group's cached event data if available to avoid per-issue Snuba calls.


@staticmethod
def get_merged_pr_single_issue_template(title: str, url: str, environment: str) -> str:
truncated_title = PRCommentWorkflow._truncate_title(title)
return MERGED_PR_SINGLE_ISSUE_TEMPLATE.format(
title=truncated_title,
url=url,
environment=environment,
)
Comment on lines +599 to +606
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 @staticmethod get_merged_pr_single_issue_template hardcodes PRCommentWorkflow._truncate_title, bypassing subclass overrides (bug)

In commit_context.py lines 599–606, get_merged_pr_single_issue_template is decorated as @staticmethod and references PRCommentWorkflow._truncate_title directly by class name:

@staticmethod
def get_merged_pr_single_issue_template(title: str, url: str, environment: str) -> str:
    truncated_title = PRCommentWorkflow._truncate_title(title)  # hardcoded class ref
    return MERGED_PR_SINGLE_ISSUE_TEMPLATE.format(...)

Since _truncate_title is also a @staticmethod, the hardcoded class reference means any subclass that overrides _truncate_title will not have its override invoked when get_merged_pr_single_issue_template is called. The fix is to either call _truncate_title(title) as a bare function reference (which also bypasses inheritance but is at least explicit), or remove the @staticmethod decorator and call cls._truncate_title(title) via @classmethod, which correctly dispatches through the MRO.

💡 Suggestion: Convert get_merged_pr_single_issue_template from a @staticmethod to a @classmethod, accepting cls as first parameter, and call cls._truncate_title(title) so that subclass overrides of _truncate_title are respected. Alternatively, if subclassing _truncate_title is not a concern, call the module-level helper directly to make the intent explicit.

📋 Prompt for AI Agents

In src/sentry/integrations/source_code_management/commit_context.py at lines 599-606, get_merged_pr_single_issue_template is a @staticmethod that calls PRCommentWorkflow._truncate_title(title) by hardcoded class name. Change it to a @classmethod by replacing @staticmethod with @classmethod, adding cls as the first parameter, and calling cls._truncate_title(title) so that subclasses overriding _truncate_title have their implementation respected. Update all three call sites in github/integration.py (line 406) and gitlab/integration.py (line 254) — they already use self.get_merged_pr_single_issue_template(...) so instance dispatch will automatically route through cls.



class OpenPRCommentWorkflow(ABC):
def __init__(self, integration: CommitContextIntegration):
Expand Down
Loading