mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
221 lines
8.9 KiB
Python
221 lines
8.9 KiB
Python
from datetime import datetime, timedelta
|
|
from unittest import mock
|
|
|
|
from django.utils import timezone
|
|
|
|
from sentry.models.activity import Activity
|
|
from sentry.models.group import Group, GroupStatus
|
|
from sentry.signals import issue_resolved
|
|
from sentry.testutils.cases import TestCase
|
|
from sentry.testutils.silo import region_silo_test
|
|
from sentry.types.activity import ActivityType
|
|
from sentry.utils.suspect_resolutions import ALGO_VERSION
|
|
from sentry.utils.suspect_resolutions.commit_correlation import CommitCorrelatedResult
|
|
from sentry.utils.suspect_resolutions.get_suspect_resolutions import get_suspect_resolutions
|
|
from sentry.utils.suspect_resolutions.metric_correlation import (
|
|
CandidateMetricCorrResult,
|
|
IssueReleaseMetricCorrResult,
|
|
)
|
|
|
|
|
|
@region_silo_test
|
|
class GetSuspectResolutionsTest(TestCase):
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(True, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[(CandidateMetricCorrResult(0, True, 0.5, 100, 100))],
|
|
timezone.now(),
|
|
timezone.now() - timedelta(days=1),
|
|
timezone.now() - timedelta(hours=2),
|
|
)
|
|
),
|
|
)
|
|
def test_get_suspect_resolutions(self):
|
|
project = self.create_project()
|
|
resolved_issue = self.create_group(
|
|
status=GroupStatus.RESOLVED,
|
|
resolved_at=timezone.now(),
|
|
project=project,
|
|
last_seen=timezone.now() - timedelta(hours=2),
|
|
)
|
|
Activity.objects.create(
|
|
project=project, group=resolved_issue, type=ActivityType.SET_RESOLVED_IN_RELEASE.value
|
|
)
|
|
|
|
assert get_suspect_resolutions(resolved_issue.id) == [0]
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(False, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[(CandidateMetricCorrResult(0, True, 0.5, 100, 100))],
|
|
timezone.now(),
|
|
timezone.now() - timedelta(days=1),
|
|
timezone.now() - timedelta(hours=2),
|
|
)
|
|
),
|
|
)
|
|
def test_get_suspect_resolutions_uncorrelated_commit_data(self):
|
|
project = self.create_project()
|
|
resolved_issue = self.create_group(
|
|
status=GroupStatus.RESOLVED, resolved_at=timezone.now(), project=project
|
|
)
|
|
self.create_group(project=project, status=GroupStatus.UNRESOLVED)
|
|
|
|
assert get_suspect_resolutions(resolved_issue.id) == []
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(True, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[(CandidateMetricCorrResult(0, False, 0.2, 100, 100))],
|
|
timezone.now(),
|
|
timezone.now() - timedelta(days=1),
|
|
timezone.now() - timedelta(hours=2),
|
|
)
|
|
),
|
|
)
|
|
def test_get_suspect_resolutions_uncorrelated_metric_data(self):
|
|
project = self.create_project()
|
|
resolved_issue = self.create_group(
|
|
status=GroupStatus.RESOLVED, resolved_at=timezone.now(), project=project
|
|
)
|
|
|
|
assert get_suspect_resolutions(resolved_issue.id) == []
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(False, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[(CandidateMetricCorrResult(0, False, 0.2, 100, 100))],
|
|
timezone.now(),
|
|
timezone.now() - timedelta(days=1),
|
|
timezone.now() - timedelta(hours=2),
|
|
)
|
|
),
|
|
)
|
|
def test_get_suspect_resolutions_uncorrelated_data(self):
|
|
project = self.create_project()
|
|
resolved_issue = self.create_group(
|
|
status=GroupStatus.RESOLVED, resolved_at=timezone.now(), project=project
|
|
)
|
|
|
|
assert get_suspect_resolutions(resolved_issue.id) == []
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(False, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(return_value=None),
|
|
)
|
|
def test_get_suspect_resolutions_issue_unresolved(self):
|
|
project = self.create_project()
|
|
unresolved_issue = self.create_group(project=project, status=GroupStatus.UNRESOLVED)
|
|
|
|
assert get_suspect_resolutions(unresolved_issue.id) == []
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(False, [], [])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[], datetime.now(), datetime.now(), datetime.now()
|
|
)
|
|
),
|
|
)
|
|
def test_get_suspect_resolutions_no_other_issues_in_project(self):
|
|
project = self.create_project()
|
|
resolved_issue = self.create_group(project=project, status=GroupStatus.RESOLVED)
|
|
|
|
assert get_suspect_resolutions(resolved_issue.id) == []
|
|
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_commit_correlated",
|
|
mock.Mock(return_value=CommitCorrelatedResult(True, [1, 2], [3, 4])),
|
|
)
|
|
@mock.patch(
|
|
"sentry.utils.suspect_resolutions.get_suspect_resolutions.is_issue_error_rate_correlated",
|
|
mock.Mock(
|
|
return_value=IssueReleaseMetricCorrResult(
|
|
[(CandidateMetricCorrResult(0, True, 0.5, 100, 100))],
|
|
datetime(2022, 1, 3),
|
|
datetime(2022, 1, 2),
|
|
datetime(2022, 1, 1),
|
|
)
|
|
),
|
|
)
|
|
@mock.patch("sentry.analytics.record")
|
|
def test_suspect_resolutions_evaluation_analytics_event(self, record):
|
|
organization = self.create_organization()
|
|
project = self.create_project(organization=organization)
|
|
resolved_issue = Group.objects.create(status=GroupStatus.RESOLVED, project=project)
|
|
resolution_type = Activity.objects.create(
|
|
project=project, group=resolved_issue, type=ActivityType.SET_RESOLVED_IN_RELEASE.value
|
|
)
|
|
get_suspect_resolutions(resolved_issue.id)
|
|
|
|
notification_record = [
|
|
r for r in record.call_args_list if r[0][0] == "suspect_resolution.evaluation"
|
|
]
|
|
|
|
assert notification_record == [
|
|
mock.call(
|
|
"suspect_resolution.evaluation",
|
|
algo_version=ALGO_VERSION,
|
|
resolved_group_id=resolved_issue.id,
|
|
candidate_group_id=0,
|
|
resolved_group_resolution_type=ActivityType(resolution_type.type).name,
|
|
pearson_r_coefficient=0.5,
|
|
pearson_r_start_time=datetime(2022, 1, 2),
|
|
pearson_r_end_time=datetime(2022, 1, 1),
|
|
pearson_r_resolution_time=datetime(2022, 1, 3),
|
|
is_commit_correlated=True,
|
|
resolved_issue_release_ids=[1, 2],
|
|
candidate_issue_release_ids=[3, 4],
|
|
resolved_issue_total_events=100,
|
|
candidate_issue_total_events=100,
|
|
)
|
|
]
|
|
|
|
@mock.patch("sentry.utils.suspect_resolutions.get_suspect_resolutions.get_suspect_resolutions")
|
|
def test_record_suspect_resolutions(self, mock_record_suspect_resolutions):
|
|
organization = self.create_organization()
|
|
project = self.create_project(organization=organization)
|
|
user = self.create_user()
|
|
resolved_issue = self.create_group(project=project)
|
|
resolution_type = "in_release"
|
|
|
|
with self.feature("projects:suspect-resolutions"):
|
|
issue_resolved.send(
|
|
organization_id=organization.id,
|
|
project=project,
|
|
group=resolved_issue,
|
|
user=user,
|
|
resolution_type=resolution_type,
|
|
sender=type(self.project),
|
|
)
|
|
|
|
assert len(mock_record_suspect_resolutions.mock_calls) == 1
|