Skip to content

Commit

Permalink
Fix N+1 issue on alert group list page (#4738)
Browse files Browse the repository at this point in the history
# What this PR does

Before:

<img width="267" alt="Screenshot 2024-07-25 at 17 35 28"
src="https://github.com/user-attachments/assets/b0cdcb9d-f658-41cf-9fbb-b61819364dec">

After:
<img width="267" alt="Screenshot 2024-07-25 at 18 11 53"
src="https://github.com/user-attachments/assets/f88c574d-ec9b-4e16-a413-62aa00de6c9a">


## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
  • Loading branch information
vstpme authored Jul 25, 2024
1 parent b408248 commit eb9e235
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 5 deletions.
18 changes: 14 additions & 4 deletions engine/apps/alerts/models/alert_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,15 @@ def slack_app_link(self) -> typing.Optional[str]:
def telegram_permalink(self) -> typing.Optional[str]:
from apps.telegram.models.message import TelegramMessage

main_telegram_message = self.telegram_messages.filter(
chat_id__startswith="-", message_type=TelegramMessage.ALERT_GROUP_MESSAGE
).first()
try:
# prefetched_telegram_messages could be set in apps.api.serializers.alert_group.AlertGroupListSerializer
main_telegram_message = self.prefetched_telegram_messages[0] if self.prefetched_telegram_messages else None
except AttributeError:
main_telegram_message = (
self.telegram_messages.filter(chat_id__startswith="-", message_type=TelegramMessage.ALERT_GROUP_MESSAGE)
.order_by("id")
.first()
)

return main_telegram_message.link if main_telegram_message else None

Expand Down Expand Up @@ -1971,7 +1977,11 @@ def slack_channel_id(self) -> str | None:

@property
def slack_message(self) -> typing.Optional["SlackMessage"]:
return self.slack_messages.order_by("created_at").first()
try:
# prefetched_slack_messages could be set in apps.api.serializers.alert_group.AlertGroupListSerializer
return self.prefetched_slack_messages[0] if self.prefetched_slack_messages else None
except AttributeError:
return self.slack_messages.order_by("created_at").first()

@cached_property
def last_stop_escalation_log(self):
Expand Down
21 changes: 20 additions & 1 deletion engine/apps/api/serializers/alert_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import logging
import typing

from django.conf import settings
from django.core.cache import cache
from django.db.models import Prefetch
from django.utils import timezone
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers

from apps.alerts.incident_appearance.renderers.web_renderer import AlertGroupWebRenderer
from apps.alerts.models import AlertGroup
from apps.alerts.models.alert_group import PagedUser
from apps.slack.models import SlackMessage
from apps.telegram.models import TelegramMessage
from common.api_helpers.custom_fields import TeamPrimaryKeyRelatedField
from common.api_helpers.mixins import EagerLoadingMixin

Expand Down Expand Up @@ -129,11 +133,26 @@ class AlertGroupListSerializer(

labels = AlertGroupLabelSerializer(many=True, read_only=True)

PREFETCH_RELATED = [
PREFETCH_RELATED: list[str | Prefetch] = [
"dependent_alert_groups",
"log_records__author",
"labels",
]
if settings.ALERT_GROUP_LIST_TRY_PREFETCH:
PREFETCH_RELATED += [
Prefetch(
"slack_messages",
queryset=SlackMessage.objects.select_related("_slack_team_identity").order_by("created_at")[:1],
to_attr="prefetched_slack_messages",
),
Prefetch(
"telegram_messages",
queryset=TelegramMessage.objects.filter(
chat_id__startswith="-", message_type=TelegramMessage.ALERT_GROUP_MESSAGE
).order_by("id")[:1],
to_attr="prefetched_telegram_messages",
),
]

SELECT_RELATED = [
"channel__organization",
Expand Down
1 change: 1 addition & 0 deletions engine/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ class DatabaseTypes:
ALERT_GROUPS_DISABLE_PREFER_ORDERING_INDEX = DATABASE_TYPE == DatabaseTypes.MYSQL and getenv_boolean(
"ALERT_GROUPS_DISABLE_PREFER_ORDERING_INDEX", default=False
)
ALERT_GROUP_LIST_TRY_PREFETCH = getenv_boolean("ALERT_GROUP_LIST_TRY_PREFETCH", default=False)

# Redis
REDIS_USERNAME = os.getenv("REDIS_USERNAME", "")
Expand Down

0 comments on commit eb9e235

Please sign in to comment.