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
2 changes: 0 additions & 2 deletions src/sentry/features/temporary.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,6 @@ def register_temporary_features(manager: FeatureManager) -> None:
manager.add("organizations:workflow-engine-action-filters-cache", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enable ingestion through trusted relays only
manager.add("organizations:ingest-through-trusted-relays-only", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable metric issue UI for issue alerts
manager.add("organizations:workflow-engine-metric-issue-ui", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Disable issue stream detector notifications for metric issues
manager.add("organizations:workflow-engine-metric-issue-disable-issue-detector-notifications", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enable new workflow_engine UI (see: alerts create issues)
Expand Down
16 changes: 1 addition & 15 deletions src/sentry/incidents/grouptype.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ class MetricIssue(GroupType):
category_v2 = GroupCategory.METRIC.value
creation_quota = Quota(3600, 60, 100)
default_priority = PriorityLevel.HIGH
released = True
enable_auto_resolve = False
enable_escalation_detection = False
enable_status_change_workflow_notifications = False
Expand All @@ -375,18 +376,3 @@ class MetricIssue(GroupType):
},
},
)

@classmethod
def allow_ingest(cls, organization: Organization) -> bool:
return True

@classmethod
def allow_post_process_group(cls, organization: Organization) -> bool:
return True

@classmethod
def build_visible_feature_name(cls) -> list[str]:
return [
"organizations:workflow-engine-ui",
"organizations:workflow-engine-metric-issue-ui",
]
14 changes: 4 additions & 10 deletions src/sentry/workflow_engine/processors/detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,31 +67,25 @@ def detectors(self) -> set[Detector]:
def _is_issue_stream_detector_enabled(event_data: WorkflowEventData) -> bool:
"""
Check if the issue stream detector should be enabled for this event's group type.

Most group types enable the issue stream detector by default. MetricIssue is excluded
unless the workflow-engine-metric-issue-ui feature flag is enabled for the organization,
which allows incremental rollout of issue alerts for metric issues.
"""
group_type_id = event_data.group.type
disabled_type_ids = options.get("workflow_engine.group.type_id.disable_issue_stream_detector")
if group_type_id not in disabled_type_ids:
return True

# Metric isssues are a special case currently.
# In order to give users time to adjust to the new behavior, we allow them to disable the
# issue stream detector for metric issues via a feature flag.
if group_type_id != MetricIssue.type_id:
return False

organization = event_data.event.project.organization

has_metric_issue_ui = features.has(
"organizations:workflow-engine-metric-issue-ui", organization
)
# For most users, the issue stream detector for metric issues will be rolled out along with the metric issue UI.
# For users who find that behavior undesirable, this feature flag will disable it for them.
disable_issue_stream_detector_for_metric_issues = features.has(
"organizations:workflow-engine-metric-issue-disable-issue-detector-notifications",
organization,
)
return has_metric_issue_ui and not disable_issue_stream_detector_for_metric_issues
return not disable_issue_stream_detector_for_metric_issues


def get_detectors_for_event_data(
Expand Down
53 changes: 11 additions & 42 deletions tests/sentry/workflow_engine/processors/test_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,6 @@ def setUp(self) -> None:
self.group_event = GroupEvent.from_event(self.event, self.group)

def test_activity_update(self) -> None:
# only picks up metric detector because the group type does not enable the issue stream detector
activity = Activity.objects.create(
project=self.project,
group=self.group,
Expand All @@ -878,7 +877,7 @@ def test_activity_update(self) -> None:
result = get_detectors_for_event_data(event_data, detector=self.detector)
assert result is not None
assert result.preferred_detector == self.detector
assert result.detectors == {self.detector}
assert result.detectors == {self.issue_stream_detector, self.detector}

def test_error_group_type(self) -> None:
# default behavior for a group type is to pick up the issue stream detector
Expand All @@ -896,30 +895,6 @@ def test_metric_issue(self) -> None:
result = get_detectors_for_event_data(event_data)
assert result is not None
assert result.preferred_detector == self.detector
assert result.detectors == {self.detector}

def test_metric_issue_with_feature_flag(self) -> None:
self.group_event.occurrence = self.occurrence

event_data = WorkflowEventData(event=self.group_event, group=self.group)
with self.feature("organizations:workflow-engine-metric-issue-ui"):
result = get_detectors_for_event_data(event_data)
assert result is not None
assert result.preferred_detector == self.detector
assert result.detectors == {self.issue_stream_detector, self.detector}

def test_activity_update_with_feature_flag(self) -> None:
activity = Activity.objects.create(
project=self.project,
group=self.group,
type=ActivityType.SET_RESOLVED.value,
user_id=self.user.id,
)
event_data = WorkflowEventData(event=activity, group=self.group)
with self.feature("organizations:workflow-engine-metric-issue-ui"):
result = get_detectors_for_event_data(event_data, detector=self.detector)
assert result is not None
assert result.preferred_detector == self.detector
assert result.detectors == {self.issue_stream_detector, self.detector}

def test_metric_issue_with_disable_detector_flag(self) -> None:
Expand All @@ -928,18 +903,15 @@ def test_metric_issue_with_disable_detector_flag(self) -> None:

event_data = WorkflowEventData(event=self.group_event, group=self.group)
with self.feature(
{
"organizations:workflow-engine-metric-issue-ui": True,
"organizations:workflow-engine-metric-issue-disable-issue-detector-notifications": True,
}
"organizations:workflow-engine-metric-issue-disable-issue-detector-notifications"
):
result = get_detectors_for_event_data(event_data)
assert result is not None
assert result.preferred_detector == self.detector
assert result.detectors == {self.detector}

def test_non_metric_issue_in_disable_list_with_feature_flag(self) -> None:
"""Feature flag override only applies to MetricIssue, not other disabled group types."""
def test_non_metric_issue_in_disable_list(self) -> None:
"""Disable override only applies to MetricIssue, not other disabled group types."""
self.group.update(type=FeedbackGroup.type_id)
activity = Activity.objects.create(
project=self.project,
Expand All @@ -948,16 +920,13 @@ def test_non_metric_issue_in_disable_list_with_feature_flag(self) -> None:
user_id=self.user.id,
)
event_data = WorkflowEventData(event=activity, group=self.group)
with (
self.feature("organizations:workflow-engine-metric-issue-ui"),
self.options(
{
"workflow_engine.group.type_id.disable_issue_stream_detector": [
MetricIssue.type_id,
FeedbackGroup.type_id,
]
}
),
with self.options(
{
"workflow_engine.group.type_id.disable_issue_stream_detector": [
MetricIssue.type_id,
FeedbackGroup.type_id,
]
}
):
result = get_detectors_for_event_data(event_data)
assert result is None
Expand Down
8 changes: 2 additions & 6 deletions tests/sentry/workflow_engine/processors/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ def test_regressed_event(self) -> None:
@patch("sentry.workflow_engine.processors.detector.logger")
def test_no_detector(self, mock_logger: MagicMock, mock_incr: MagicMock) -> None:
self.group_event.occurrence = self.build_occurrence(evidence_data={})
self.issue_stream_detector.delete()

result = process_workflows(self.batch_client, self.event_data, FROZEN_TIME)
assert result.msg == "No Detectors associated with the issue were found"
Expand Down Expand Up @@ -446,13 +447,8 @@ def test_uses_issue_stream_workflows(self) -> None:
assert len(result.data.triggered_actions) == 0

def test_multiple_detectors__preferred(self) -> None:
_, issue_stream_detector, _, _ = self.create_detector_and_workflow(
name_prefix="issue_stream",
workflow_triggers=self.create_data_condition_group(),
detector_type=IssueStreamGroupType.slug,
)
self.create_detector_workflow(
detector=issue_stream_detector,
detector=self.issue_stream_detector,
workflow=self.error_workflow,
)

Expand Down
23 changes: 0 additions & 23 deletions tests/snuba/search/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from sentry.exceptions import InvalidSearchQuery
from sentry.grouping.grouptype import ErrorGroupType
from sentry.incidents.grouptype import MetricIssue
from sentry.issues.grouptype import (
FeedbackGroup,
NoiseConfig,
Expand Down Expand Up @@ -3489,28 +3488,6 @@ def setUp(self) -> None:
)
self.error_group_2 = error_event_2.group

def test_no_feature(self) -> None:
event_id = uuid.uuid4().hex

with self.feature(MetricIssue.build_ingest_feature_name()):
_, group_info = self.process_occurrence(
event_id=event_id,
project_id=self.project.id,
type=MetricIssue.type_id,
fingerprint=["some perf issue"],
event_data={
"title": "some problem",
"platform": "python",
"tags": {"my_tag": "1"},
"timestamp": before_now(minutes=1).isoformat(),
"received": before_now(minutes=1).isoformat(),
},
)
assert group_info is not None

results = self.make_query(search_filter_query="issue.category:metric_alert my_tag:1")
assert list(results) == []

def test_generic_query(self) -> None:
results = self.make_query(search_filter_query="issue.category:performance my_tag:1")
assert list(results) == [self.profile_group_1, self.profile_group_2]
Expand Down
Loading