Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pr_filtering): Initial implementation of PR filtering for Incidents #633

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
47 changes: 38 additions & 9 deletions backend/analytics_server/mhq/api/incidents.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,26 @@
{
Required("from_time"): All(str, Coerce(datetime.fromisoformat)),
Required("to_time"): All(str, Coerce(datetime.fromisoformat)),
Optional("pr_filter"): All(str, Coerce(json.loads)),
}
),
)
def get_resolved_incidents(team_id: str, from_time: datetime, to_time: datetime):
def get_resolved_incidents(
team_id: str, from_time: datetime, to_time: datetime, pr_filter: dict = None
):

query_validator = get_query_validator()
interval = query_validator.interval_validator(from_time, to_time)
query_validator.team_validator(team_id)

pr_filter: PRFilter = apply_pr_filter(
pr_filter, EntityType.TEAM, team_id, [SettingType.EXCLUDED_PRS_SETTING]
)

incident_service = get_incident_service()

resolved_incidents: List[Incident] = incident_service.get_resolved_team_incidents(
team_id, interval
team_id, interval, pr_filter
)

# ToDo: Generate a user map
Expand Down Expand Up @@ -90,7 +97,9 @@ def get_deployments_with_related_incidents(

incident_service = get_incident_service()

incidents: List[Incident] = incident_service.get_team_incidents(team_id, interval)
incidents: List[Incident] = incident_service.get_team_incidents(
team_id, interval, pr_filter
)

deployment_incidents_map: Dict[Deployment, List[Incident]] = (
incident_service.get_deployment_incidents_map(deployments, incidents)
Expand All @@ -112,18 +121,25 @@ def get_deployments_with_related_incidents(
{
Required("from_time"): All(str, Coerce(datetime.fromisoformat)),
Required("to_time"): All(str, Coerce(datetime.fromisoformat)),
Optional("pr_filter"): All(str, Coerce(json.loads)),
}
),
)
def get_team_mttr(team_id: str, from_time: datetime, to_time: datetime):
def get_team_mttr(
team_id: str, from_time: datetime, to_time: datetime, pr_filter: dict = None
):
query_validator = get_query_validator()
interval = query_validator.interval_validator(from_time, to_time)
query_validator.team_validator(team_id)

pr_filter: PRFilter = apply_pr_filter(
pr_filter, EntityType.TEAM, team_id, [SettingType.EXCLUDED_PRS_SETTING]
)

incident_service = get_incident_service()

team_mean_time_to_recovery_metrics = (
incident_service.get_team_mean_time_to_recovery(team_id, interval)
incident_service.get_team_mean_time_to_recovery(team_id, interval, pr_filter)
)

return adapt_mean_time_to_recovery_metrics(team_mean_time_to_recovery_metrics)
Expand All @@ -135,18 +151,27 @@ def get_team_mttr(team_id: str, from_time: datetime, to_time: datetime):
{
Required("from_time"): All(str, Coerce(datetime.fromisoformat)),
Required("to_time"): All(str, Coerce(datetime.fromisoformat)),
Optional("pr_filter"): All(str, Coerce(json.loads)),
}
),
)
def get_team_mttr_trends(team_id: str, from_time: datetime, to_time: datetime):
def get_team_mttr_trends(
team_id: str, from_time: datetime, to_time: datetime, pr_filter: dict = None
):
query_validator = get_query_validator()
interval = query_validator.interval_validator(from_time, to_time)
query_validator.team_validator(team_id)

pr_filter: PRFilter = apply_pr_filter(
pr_filter, EntityType.TEAM, team_id, [SettingType.EXCLUDED_PRS_SETTING]
)

incident_service = get_incident_service()

weekly_mean_time_to_recovery_metrics = (
incident_service.get_team_mean_time_to_recovery_trends(team_id, interval)
incident_service.get_team_mean_time_to_recovery_trends(
team_id, interval, pr_filter
)
)

return {
Expand Down Expand Up @@ -192,7 +217,9 @@ def get_team_cfr(

incident_service = get_incident_service()

incidents: List[Incident] = incident_service.get_team_incidents(team_id, interval)
incidents: List[Incident] = incident_service.get_team_incidents(
team_id, interval, pr_filter
)

team_change_failure_rate: ChangeFailureRateMetrics = (
incident_service.get_change_failure_rate_metrics(deployments, incidents)
Expand Down Expand Up @@ -236,7 +263,9 @@ def get_team_cfr_trends(

incident_service = get_incident_service()

incidents: List[Incident] = incident_service.get_team_incidents(team_id, interval)
incidents: List[Incident] = incident_service.get_team_incidents(
team_id, interval, pr_filter
)

team_weekly_change_failure_rate: Dict[datetime, ChangeFailureRateMetrics] = (
incident_service.get_weekly_change_failure_rate(
Expand Down
12 changes: 11 additions & 1 deletion backend/analytics_server/mhq/api/resources/settings_resource.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from mhq.service.settings.models import (
ConfigurationSettings,
DefaultSyncDaysSetting,
IncidentSettings,
ExcludedPRsSetting,
IncidentTypesSetting,
IncidentSourcesSetting,
DefaultSyncDaysSetting,
IncidentPrsSetting,
)
from mhq.store.models import EntityType

Expand Down Expand Up @@ -55,6 +56,15 @@ def _add_setting_data(config_settings: ConfigurationSettings, response):
"default_sync_days": config_settings.specific_settings.default_sync_days
}

if isinstance(config_settings.specific_settings, IncidentPrsSetting):
response["setting"] = {
"include_revert_prs": config_settings.specific_settings.include_revert_prs,
"title_filters": config_settings.specific_settings.title_filters,
"head_branch_filters": config_settings.specific_settings.head_branch_filters,
"pr_mapping_field": config_settings.specific_settings.pr_mapping_field,
"pr_mapping_pattern": config_settings.specific_settings.pr_mapping_pattern,
}

# ADD NEW API ADAPTER HERE

return response
Expand Down
17 changes: 17 additions & 0 deletions backend/analytics_server/mhq/service/incidents/incident_filter.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from typing import Dict, List, Any, Optional
from mhq.store.models.incidents.enums import IncidentType
from mhq.store.models.settings.configuration_settings import SettingType
from mhq.service.settings.configuration_settings import (
get_settings_service,
IncidentSettings,
IncidentTypesSetting,
IncidentPrsSetting,
)
from mhq.store.models.incidents import IncidentFilter

Expand Down Expand Up @@ -106,4 +108,19 @@ def __incident_type_setting(self) -> List[str]:
incident_types = []
if setting and isinstance(setting, IncidentTypesSetting):
incident_types = setting.incident_types

if SettingType.INCIDENT_PRS_SETTING in self.setting_types:
incident_prs_setting: Optional[IncidentPrsSetting] = (
self.setting_type_to_settings_map.get(SettingType.INCIDENT_PRS_SETTING)
)
if (
isinstance(incident_prs_setting, IncidentPrsSetting)
and not incident_prs_setting.include_revert_prs
):
incident_types = [
incident_type
for incident_type in incident_types
if incident_type != IncidentType.REVERT_PR
]

return incident_types
Loading
Loading