Optimize duplicate queries occurring in AlertGroupFilter (#1809)
# What this PR does In `AlertGroupFilter` we currently have 11 duplicate queries which add ~1-2secs of unecessary request latency to `GET /api/internal/v1/alertgroups` calls.  The queries originate from the `queryset` callable arguments on several of the fields of the `AlertGroupFilter` class. These callables basically filter down their respective querysets to include only objects that belong to the currently authenticated user's organization. The duplicate queries are - 2 queries to fetch integrations - 2 queries to fetch escalation chains - 10 queries to fetch users At the moment, this PR is still a draft and doesn't work as intended. It's based off of [a suggestion from this discussion](https://github.com/carltongibson/django-filter/discussions/1572#discussioncomment-5676042) in the `django-filter` repo. See [this DjangoCon talk](https://youtu.be/e52S1SjuUeM?t=841) for more context. --------- Co-authored-by: Ildar Iskhakov <Ildar.iskhakov@grafana.com>
This commit is contained in:
parent
23c7a6f682
commit
52ff041066
2 changed files with 37 additions and 8 deletions
|
|
@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Add 2, 3 and 6 hours silence options
|
||||
|
||||
## Fixed
|
||||
|
||||
- Optimize duplicate queries occurring in AlertGroupFilter by @joeyorlando ([1809](https://github.com/grafana/oncall/pull/1809))
|
||||
|
||||
## v1.2.15 (2023-04-24)
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -53,6 +53,31 @@ def get_user_queryset(request):
|
|||
return User.objects.filter(organization=request.user.organization).distinct()
|
||||
|
||||
|
||||
class AlertGroupFilterBackend(filters.DjangoFilterBackend):
|
||||
"""
|
||||
See here for more context on how this works
|
||||
|
||||
https://github.com/carltongibson/django-filter/discussions/1572
|
||||
https://youtu.be/e52S1SjuUeM?t=841
|
||||
"""
|
||||
|
||||
def get_filterset(self, request, queryset, view):
|
||||
filterset = super().get_filterset(request, queryset, view)
|
||||
|
||||
filterset.form.fields["integration"].queryset = get_integration_queryset(request)
|
||||
filterset.form.fields["escalation_chain"].queryset = get_escalation_chain_queryset(request)
|
||||
|
||||
user_queryset = get_user_queryset(request)
|
||||
|
||||
filterset.form.fields["silenced_by"].queryset = user_queryset
|
||||
filterset.form.fields["acknowledged_by"].queryset = user_queryset
|
||||
filterset.form.fields["resolved_by"].queryset = user_queryset
|
||||
filterset.form.fields["invitees_are"].queryset = user_queryset
|
||||
filterset.form.fields["involved_users_are"].queryset = user_queryset
|
||||
|
||||
return filterset
|
||||
|
||||
|
||||
class AlertGroupFilter(DateRangeFilterMixin, ByTeamModelFieldFilterMixin, ModelFieldFilterMixin, filters.FilterSet):
|
||||
"""
|
||||
Examples of possible date formats here https://docs.djangoproject.com/en/1.9/ref/settings/#datetime-input-formats
|
||||
|
|
@ -69,19 +94,19 @@ class AlertGroupFilter(DateRangeFilterMixin, ByTeamModelFieldFilterMixin, ModelF
|
|||
silenced_at = filters.CharFilter(field_name="silenced_at", method=DateRangeFilterMixin.filter_date_range.__name__)
|
||||
silenced_by = filters.ModelMultipleChoiceFilter(
|
||||
field_name="silenced_by_user",
|
||||
queryset=get_user_queryset,
|
||||
queryset=None,
|
||||
to_field_name="public_primary_key",
|
||||
method=ModelFieldFilterMixin.filter_model_field.__name__,
|
||||
)
|
||||
integration = filters.ModelMultipleChoiceFilter(
|
||||
field_name="channel_filter__alert_receive_channel",
|
||||
queryset=get_integration_queryset,
|
||||
queryset=None,
|
||||
to_field_name="public_primary_key",
|
||||
method=ModelFieldFilterMixin.filter_model_field.__name__,
|
||||
)
|
||||
escalation_chain = filters.ModelMultipleChoiceFilter(
|
||||
field_name="channel_filter__escalation_chain",
|
||||
queryset=get_escalation_chain_queryset,
|
||||
queryset=None,
|
||||
to_field_name="public_primary_key",
|
||||
method=ModelFieldFilterMixin.filter_model_field.__name__,
|
||||
)
|
||||
|
|
@ -90,21 +115,21 @@ class AlertGroupFilter(DateRangeFilterMixin, ByTeamModelFieldFilterMixin, ModelF
|
|||
)
|
||||
resolved_by = filters.ModelMultipleChoiceFilter(
|
||||
field_name="resolved_by_user",
|
||||
queryset=get_user_queryset,
|
||||
queryset=None,
|
||||
to_field_name="public_primary_key",
|
||||
method=ModelFieldFilterMixin.filter_model_field.__name__,
|
||||
)
|
||||
acknowledged_by = filters.ModelMultipleChoiceFilter(
|
||||
field_name="acknowledged_by_user",
|
||||
queryset=get_user_queryset,
|
||||
queryset=None,
|
||||
to_field_name="public_primary_key",
|
||||
method=ModelFieldFilterMixin.filter_model_field.__name__,
|
||||
)
|
||||
invitees_are = filters.ModelMultipleChoiceFilter(
|
||||
queryset=get_user_queryset, to_field_name="public_primary_key", method="filter_invitees_are"
|
||||
queryset=None, to_field_name="public_primary_key", method="filter_invitees_are"
|
||||
)
|
||||
involved_users_are = filters.ModelMultipleChoiceFilter(
|
||||
queryset=get_user_queryset, to_field_name="public_primary_key", method="filter_by_involved_users"
|
||||
queryset=None, to_field_name="public_primary_key", method="filter_by_involved_users"
|
||||
)
|
||||
with_resolution_note = filters.BooleanFilter(method="filter_with_resolution_note")
|
||||
mine = filters.BooleanFilter(method="filter_mine")
|
||||
|
|
@ -270,7 +295,7 @@ class AlertGroupView(
|
|||
|
||||
pagination_class = TwentyFiveCursorPaginator
|
||||
|
||||
filter_backends = [SearchFilter, filters.DjangoFilterBackend]
|
||||
filter_backends = [SearchFilter, AlertGroupFilterBackend]
|
||||
search_fields = ["public_primary_key", "inside_organization_number", "web_title_cache"]
|
||||
|
||||
filterset_class = AlertGroupFilter
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue