2024-07-09 11:23:53 -04:00
|
|
|
import typing
|
2023-11-29 09:01:30 -03:00
|
|
|
from functools import partial
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
from uuid import uuid4
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2024-01-24 16:31:56 +01:00
|
|
|
from celery.exceptions import Retry
|
2022-06-03 08:09:47 -06:00
|
|
|
from django.conf import settings
|
|
|
|
|
from django.db import transaction
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
from django.db.models import Count
|
2022-06-03 08:09:47 -06:00
|
|
|
from django.utils import timezone
|
2023-06-27 12:23:08 +02:00
|
|
|
from kombu.utils.uuid import uuid as celery_uuid
|
2024-01-24 16:31:56 +01:00
|
|
|
from telegram.error import RetryAfter
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
from apps.alerts.constants import NEXT_ESCALATION_DELAY
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
from apps.alerts.tasks.send_update_log_report_signal import send_update_log_report_signal
|
2022-06-03 08:09:47 -06:00
|
|
|
from apps.base.messaging import get_messaging_backend_from_id
|
2023-11-29 20:45:36 +08:00
|
|
|
from apps.metrics_exporter.tasks import update_metrics_for_user
|
2023-05-24 14:27:48 +08:00
|
|
|
from apps.phone_notifications.phone_backend import PhoneBackend
|
2022-06-03 08:09:47 -06:00
|
|
|
from common.custom_celery_tasks import shared_dedicated_queue_retry_task
|
|
|
|
|
|
|
|
|
|
from .task_logger import task_logger
|
|
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
if typing.TYPE_CHECKING:
|
|
|
|
|
from apps.alerts.models import AlertGroup, UserNotificationBundle
|
|
|
|
|
from apps.base.models import UserNotificationPolicy
|
|
|
|
|
from apps.user_management.models import User
|
|
|
|
|
|
|
|
|
|
|
2024-10-15 10:35:54 -03:00
|
|
|
RETRY_TIMEOUT_HOURS = 1
|
|
|
|
|
|
|
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
def schedule_send_bundled_notification_task(
|
|
|
|
|
user_notification_bundle: "UserNotificationBundle", alert_group: "AlertGroup"
|
|
|
|
|
):
|
|
|
|
|
"""Schedule a task to send bundled notifications"""
|
|
|
|
|
send_bundled_notification.apply_async(
|
|
|
|
|
(user_notification_bundle.id,),
|
|
|
|
|
eta=user_notification_bundle.eta,
|
|
|
|
|
task_id=user_notification_bundle.notification_task_id,
|
|
|
|
|
)
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"Scheduled send_bundled_notification task {user_notification_bundle.notification_task_id}, "
|
|
|
|
|
f"user_notification_bundle: {user_notification_bundle.id}, alert_group {alert_group.id}, "
|
|
|
|
|
f"eta: {user_notification_bundle.eta}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def schedule_perform_notification_task(
|
|
|
|
|
log_record_pk: int, alert_group_pk: int, use_default_notification_policy_fallback: bool
|
|
|
|
|
):
|
|
|
|
|
task = perform_notification.apply_async((log_record_pk, use_default_notification_policy_fallback))
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"Created perform_notification task {task} log_record={log_record_pk} " f"alert_group={alert_group_pk}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_notification_reason_for_log_record(
|
|
|
|
|
notification_policies: typing.List["UserNotificationPolicy"], reason: typing.Optional[str]
|
|
|
|
|
) -> str:
|
|
|
|
|
from apps.base.models import UserNotificationPolicy
|
|
|
|
|
|
|
|
|
|
# Here we collect a brief overview of notification steps configured for user to send it to thread.
|
|
|
|
|
collected_steps_ids = []
|
|
|
|
|
for next_notification_policy in notification_policies:
|
|
|
|
|
if next_notification_policy.step == UserNotificationPolicy.Step.NOTIFY:
|
|
|
|
|
if next_notification_policy.notify_by not in collected_steps_ids:
|
|
|
|
|
collected_steps_ids.append(next_notification_policy.notify_by)
|
|
|
|
|
|
|
|
|
|
collected_steps = ", ".join(
|
|
|
|
|
UserNotificationPolicy.NotificationChannel(step_id).label for step_id in collected_steps_ids
|
|
|
|
|
)
|
|
|
|
|
reason = ("Reason: " + reason + "\n") if reason is not None else ""
|
|
|
|
|
reason += ("Further notification plan: " + collected_steps) if len(collected_steps_ids) > 0 else ""
|
|
|
|
|
return reason
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_metric_if_needed(user: "User", active_alert_group_ids: typing.List[int]):
|
|
|
|
|
from apps.base.models import UserNotificationPolicyLogRecord
|
|
|
|
|
|
|
|
|
|
# get count of alert groups with only one personal log record with type "triggered"
|
|
|
|
|
alert_groups_with_one_log = (
|
|
|
|
|
user.personal_log_records.filter(
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED,
|
|
|
|
|
alert_group_id__in=active_alert_group_ids,
|
|
|
|
|
)
|
|
|
|
|
.values("alert_group")
|
|
|
|
|
.annotate(count=Count("alert_group"))
|
|
|
|
|
.filter(count=1)
|
|
|
|
|
.count()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if alert_groups_with_one_log > 0:
|
|
|
|
|
update_metrics_for_user.apply_async((user.id, alert_groups_with_one_log))
|
|
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
@shared_dedicated_queue_retry_task(
|
|
|
|
|
autoretry_for=(Exception,), retry_backoff=True, max_retries=1 if settings.DEBUG else None
|
|
|
|
|
)
|
|
|
|
|
def notify_user_task(
|
|
|
|
|
user_pk,
|
|
|
|
|
alert_group_pk,
|
|
|
|
|
previous_notification_policy_pk=None,
|
|
|
|
|
reason=None,
|
|
|
|
|
prevent_posting_to_thread=False,
|
|
|
|
|
notify_even_acknowledged=False,
|
|
|
|
|
important=False,
|
|
|
|
|
notify_anyway=False,
|
|
|
|
|
):
|
2024-08-30 10:17:09 +01:00
|
|
|
from apps.alerts.models import AlertGroup, AlertGroupLogRecord, UserHasNotification, UserNotificationBundle
|
2023-07-25 10:43:23 +01:00
|
|
|
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
|
|
|
|
|
from apps.user_management.models import User
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
try:
|
2023-07-18 13:48:34 +02:00
|
|
|
alert_group = AlertGroup.objects.get(pk=alert_group_pk)
|
2022-06-03 08:09:47 -06:00
|
|
|
except AlertGroup.DoesNotExist:
|
|
|
|
|
return f"notify_user_task: alert_group {alert_group_pk} doesn't exist"
|
|
|
|
|
|
|
|
|
|
countdown = 0
|
|
|
|
|
stop_escalation = False
|
|
|
|
|
log_record = None
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
is_notification_bundled = False
|
|
|
|
|
user_notification_bundle = None
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
with transaction.atomic():
|
|
|
|
|
try:
|
|
|
|
|
user = User.objects.get(pk=user_pk)
|
|
|
|
|
except User.DoesNotExist:
|
|
|
|
|
return f"notify_user_task: user {user_pk} doesn't exist"
|
|
|
|
|
|
|
|
|
|
if not user.is_notification_allowed:
|
2022-11-29 09:41:56 +01:00
|
|
|
task_logger.info(f"notify_user_task: user {user.pk} notification is not allowed")
|
2022-06-13 16:39:58 -06:00
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
2023-07-26 14:45:44 +01:00
|
|
|
reason="notification is not allowed for user",
|
2022-06-13 16:39:58 -06:00
|
|
|
alert_group=alert_group,
|
2022-11-29 09:41:56 +01:00
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_FORBIDDEN,
|
2022-06-13 16:39:58 -06:00
|
|
|
).save()
|
2022-06-03 08:09:47 -06:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
user_has_notification, _ = UserHasNotification.objects.get_or_create(
|
|
|
|
|
user=user,
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
user_has_notification = UserHasNotification.objects.filter(pk=user_has_notification.pk).select_for_update()[0]
|
2024-07-08 13:04:16 -04:00
|
|
|
using_fallback_default_notification_policy_step = False
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
if previous_notification_policy_pk is None:
|
2024-07-08 13:04:16 -04:00
|
|
|
(
|
|
|
|
|
using_fallback_default_notification_policy_step,
|
|
|
|
|
notification_policies,
|
|
|
|
|
) = user.get_notification_policies_or_use_default_fallback(important=important)
|
2024-07-05 15:08:17 -04:00
|
|
|
if not notification_policies:
|
2022-08-26 14:26:01 +05:00
|
|
|
task_logger.info(
|
|
|
|
|
f"notify_user_task: Failed to notify. No notification policies. user_id={user_pk} alert_group_id={alert_group_pk} important={important}"
|
|
|
|
|
)
|
|
|
|
|
return
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
reason = build_notification_reason_for_log_record(notification_policies, reason)
|
2024-07-08 11:52:20 -04:00
|
|
|
notification_policy = notification_policies[0]
|
2022-06-03 08:09:47 -06:00
|
|
|
else:
|
|
|
|
|
if notify_user_task.request.id != user_has_notification.active_notification_policy_id:
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"notify_user_task: active_notification_policy_id mismatch. "
|
|
|
|
|
f"Duplication or non-active escalation triggered. "
|
|
|
|
|
f"Active: {user_has_notification.active_notification_policy_id}"
|
|
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
notification_policy = UserNotificationPolicy.objects.get(pk=previous_notification_policy_pk)
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
if notification_policy.user != user:
|
2022-06-03 08:09:47 -06:00
|
|
|
notification_policy = UserNotificationPolicy.objects.get(
|
|
|
|
|
order=notification_policy.order, user=user, important=important
|
|
|
|
|
)
|
|
|
|
|
notification_policy = notification_policy.next()
|
|
|
|
|
except UserNotificationPolicy.DoesNotExist:
|
|
|
|
|
task_logger.info(
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
f"notify_user_task: Notification policy {previous_notification_policy_pk} has been deleted"
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
reason = None
|
2024-07-08 13:04:16 -04:00
|
|
|
|
|
|
|
|
def _create_user_notification_policy_log_record(**kwargs):
|
2024-07-09 11:23:53 -04:00
|
|
|
return UserNotificationPolicyLogRecord(
|
|
|
|
|
**kwargs,
|
|
|
|
|
using_fallback_default_notification_policy_step=using_fallback_default_notification_policy_step,
|
|
|
|
|
)
|
2024-07-08 13:04:16 -04:00
|
|
|
|
2024-07-09 11:23:53 -04:00
|
|
|
def _create_notification_finished_user_notification_policy_log_record():
|
|
|
|
|
return _create_user_notification_policy_log_record(
|
2022-06-03 08:09:47 -06:00
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FINISHED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
slack_prevent_posting=prevent_posting_to_thread,
|
|
|
|
|
)
|
2024-07-09 11:23:53 -04:00
|
|
|
|
|
|
|
|
if notification_policy is None:
|
|
|
|
|
stop_escalation = True
|
|
|
|
|
log_record = _create_notification_finished_user_notification_policy_log_record()
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
task_logger.info(f"Personal escalation exceeded. User: {user.pk}, alert_group: {alert_group.pk}")
|
2022-06-03 08:09:47 -06:00
|
|
|
else:
|
2024-08-30 10:17:09 +01:00
|
|
|
if (
|
|
|
|
|
# don't force notify direct paged user who has already acknowledged the alert group
|
|
|
|
|
# after the last time they were paged.
|
|
|
|
|
notify_even_acknowledged
|
|
|
|
|
and (
|
|
|
|
|
direct_paging_log_record := alert_group.log_records.filter(
|
|
|
|
|
type=AlertGroupLogRecord.TYPE_DIRECT_PAGING, step_specific_info__user=user.public_primary_key
|
|
|
|
|
).last()
|
|
|
|
|
)
|
|
|
|
|
and alert_group.log_records.filter(
|
|
|
|
|
type=AlertGroupLogRecord.TYPE_ACK, author=user, created_at__gte=direct_paging_log_record.created_at
|
|
|
|
|
).exists()
|
|
|
|
|
):
|
|
|
|
|
notify_even_acknowledged = False
|
|
|
|
|
task_logger.info(f"notify_even_acknowledged=False for user {user.pk}, alert_group {alert_group.pk})")
|
|
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
if (
|
|
|
|
|
(alert_group.acknowledged and not notify_even_acknowledged)
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
or (alert_group.silenced and not notify_anyway)
|
2022-06-03 08:09:47 -06:00
|
|
|
or alert_group.resolved
|
|
|
|
|
or alert_group.wiped_at
|
|
|
|
|
or alert_group.root_alert_group
|
|
|
|
|
):
|
|
|
|
|
task_logger.info(
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
f"notify_user_task: skip notification user {user.pk}, alert_group {alert_group.pk} is "
|
|
|
|
|
f"{alert_group.state} and/or attached or wiped"
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
return "Acknowledged, resolved, silenced, attached or wiped."
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
if notification_policy.step == UserNotificationPolicy.Step.WAIT:
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
countdown = (
|
|
|
|
|
notification_policy.wait_delay.total_seconds() if notification_policy.wait_delay is not None else 0
|
|
|
|
|
)
|
2024-07-08 13:04:16 -04:00
|
|
|
log_record = _create_user_notification_policy_log_record(
|
2022-06-03 08:09:47 -06:00
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
slack_prevent_posting=prevent_posting_to_thread,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
)
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
task_logger.info(f"notify_user_task: Waiting {countdown} to notify user {user.pk}")
|
2022-06-03 08:09:47 -06:00
|
|
|
elif notification_policy.step == UserNotificationPolicy.Step.NOTIFY:
|
|
|
|
|
user_to_be_notified_in_slack = (
|
|
|
|
|
notification_policy.notify_by == UserNotificationPolicy.NotificationChannel.SLACK
|
|
|
|
|
)
|
|
|
|
|
if user_to_be_notified_in_slack and alert_group.notify_in_slack_enabled is False:
|
2024-07-08 13:04:16 -04:00
|
|
|
log_record = _create_user_notification_policy_log_record(
|
2022-06-03 08:09:47 -06:00
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
alert_group=alert_group,
|
2025-01-21 14:05:39 -03:00
|
|
|
reason="Alert group Slack notifications are disabled",
|
2022-06-03 08:09:47 -06:00
|
|
|
slack_prevent_posting=prevent_posting_to_thread,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_policy.notify_by,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_POSTING_TO_SLACK_IS_DISABLED,
|
|
|
|
|
)
|
|
|
|
|
else:
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
if (
|
|
|
|
|
settings.FEATURE_NOTIFICATION_BUNDLE_ENABLED
|
|
|
|
|
and UserNotificationBundle.notification_is_bundleable(notification_policy.notify_by)
|
|
|
|
|
):
|
|
|
|
|
user_notification_bundle, _ = UserNotificationBundle.objects.select_for_update().get_or_create(
|
|
|
|
|
user=user, important=important, notification_channel=notification_policy.notify_by
|
|
|
|
|
)
|
|
|
|
|
# check if notification needs to be bundled
|
|
|
|
|
if user_notification_bundle.notified_recently():
|
|
|
|
|
user_notification_bundle.append_notification(alert_group, notification_policy)
|
|
|
|
|
# schedule send_bundled_notification task if it hasn't been scheduled or the task eta is
|
|
|
|
|
# outdated
|
|
|
|
|
eta_is_valid = user_notification_bundle.eta_is_valid()
|
|
|
|
|
if not eta_is_valid:
|
|
|
|
|
task_logger.warning(
|
|
|
|
|
f"ETA is not valid - {user_notification_bundle.eta}, "
|
|
|
|
|
f"user_notification_bundle {user_notification_bundle.id}, "
|
|
|
|
|
f"task_id {user_notification_bundle.notification_task_id}. "
|
|
|
|
|
f"Rescheduling the send_bundled_notification task"
|
|
|
|
|
)
|
|
|
|
|
if not user_notification_bundle.notification_task_id or not eta_is_valid:
|
|
|
|
|
user_notification_bundle.notification_task_id = celery_uuid()
|
|
|
|
|
user_notification_bundle.eta = user_notification_bundle.get_notification_eta()
|
|
|
|
|
user_notification_bundle.save(update_fields=["notification_task_id", "eta"])
|
|
|
|
|
|
|
|
|
|
transaction.on_commit(
|
|
|
|
|
partial(
|
|
|
|
|
schedule_send_bundled_notification_task, user_notification_bundle, alert_group
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
is_notification_bundled = True
|
|
|
|
|
|
|
|
|
|
if not is_notification_bundled:
|
|
|
|
|
log_record = _create_user_notification_policy_log_record(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
reason=reason,
|
|
|
|
|
slack_prevent_posting=prevent_posting_to_thread,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_policy.notify_by,
|
|
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
if log_record: # log_record is None if user notification policy step is unspecified
|
2023-06-28 10:15:19 +02:00
|
|
|
# if this is the first notification step, and user hasn't been notified for this alert group - update metric
|
|
|
|
|
if (
|
|
|
|
|
log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED
|
|
|
|
|
and previous_notification_policy_pk is None
|
|
|
|
|
and not user.personal_log_records.filter(
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED,
|
|
|
|
|
alert_group_id=alert_group_pk,
|
|
|
|
|
).exists()
|
|
|
|
|
):
|
2023-11-29 20:45:36 +08:00
|
|
|
update_metrics_for_user.apply_async((user.id,))
|
2022-06-03 08:09:47 -06:00
|
|
|
log_record.save()
|
2024-07-09 11:23:53 -04:00
|
|
|
|
|
|
|
|
if using_fallback_default_notification_policy_step:
|
|
|
|
|
# if we are using default notification policy, we're done escalating.. there's no further notification
|
|
|
|
|
# policy steps in this case. Kick off the perform_notification task, create the
|
|
|
|
|
# TYPE_PERSONAL_NOTIFICATION_FINISHED log record, and reset the active_notification_policy_id
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
transaction.on_commit(
|
|
|
|
|
partial(
|
|
|
|
|
schedule_perform_notification_task,
|
|
|
|
|
log_record.pk,
|
|
|
|
|
alert_group_pk,
|
|
|
|
|
using_fallback_default_notification_policy_step,
|
|
|
|
|
)
|
|
|
|
|
)
|
2024-07-09 11:23:53 -04:00
|
|
|
_create_notification_finished_user_notification_policy_log_record()
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
user_has_notification.update_active_task_id(None)
|
2024-07-09 11:23:53 -04:00
|
|
|
elif not stop_escalation:
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
# if the step is NOTIFY and notification was not not bundled, perform regular notification
|
|
|
|
|
# and update time when user was notified
|
|
|
|
|
if notification_policy.step != UserNotificationPolicy.Step.WAIT and not is_notification_bundled:
|
|
|
|
|
transaction.on_commit(
|
|
|
|
|
partial(
|
|
|
|
|
schedule_perform_notification_task,
|
|
|
|
|
log_record.pk,
|
|
|
|
|
alert_group_pk,
|
|
|
|
|
using_fallback_default_notification_policy_step,
|
|
|
|
|
)
|
|
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
if user_notification_bundle:
|
|
|
|
|
user_notification_bundle.last_notified_at = timezone.now()
|
|
|
|
|
user_notification_bundle.save(update_fields=["last_notified_at"])
|
2022-06-03 08:09:47 -06:00
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
task_id = celery_uuid()
|
|
|
|
|
user_has_notification.update_active_task_id(task_id)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
transaction.on_commit(
|
2023-11-29 09:01:30 -03:00
|
|
|
partial(
|
|
|
|
|
notify_user_task.apply_async,
|
2022-06-03 08:09:47 -06:00
|
|
|
(user.pk, alert_group.pk, notification_policy.pk, reason),
|
|
|
|
|
{
|
|
|
|
|
"notify_even_acknowledged": notify_even_acknowledged,
|
|
|
|
|
"notify_anyway": notify_anyway,
|
|
|
|
|
"prevent_posting_to_thread": prevent_posting_to_thread,
|
|
|
|
|
},
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
countdown=countdown + NEXT_ESCALATION_DELAY,
|
2022-06-03 08:09:47 -06:00
|
|
|
task_id=task_id,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
user_has_notification.update_active_task_id(None)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@shared_dedicated_queue_retry_task(
|
2024-01-24 16:31:56 +01:00
|
|
|
autoretry_for=(Exception,),
|
|
|
|
|
retry_backoff=True,
|
|
|
|
|
dont_autoretry_for=(Retry,),
|
|
|
|
|
max_retries=1 if settings.DEBUG else None,
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
2024-07-09 11:23:53 -04:00
|
|
|
def perform_notification(log_record_pk, use_default_notification_policy_fallback):
|
2023-07-25 10:43:23 +01:00
|
|
|
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
|
|
|
|
|
from apps.telegram.models import TelegramToUserConnector
|
|
|
|
|
|
2023-11-21 13:35:23 -05:00
|
|
|
task_logger.info(f"perform_notification: log_record {log_record_pk}")
|
|
|
|
|
|
2024-01-18 07:07:01 -05:00
|
|
|
try:
|
|
|
|
|
log_record = UserNotificationPolicyLogRecord.objects.get(pk=log_record_pk)
|
|
|
|
|
except UserNotificationPolicyLogRecord.DoesNotExist:
|
|
|
|
|
task_logger.warning(
|
|
|
|
|
f"perform_notification: log_record {log_record_pk} doesn't exist. Skipping remainder of task. "
|
|
|
|
|
"The alert group associated with this log record may have been deleted."
|
|
|
|
|
)
|
|
|
|
|
return
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2024-01-18 07:07:01 -05:00
|
|
|
task_logger.info(f"perform_notification: found record for {log_record_pk}")
|
2023-11-21 13:35:23 -05:00
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
user = log_record.author
|
|
|
|
|
alert_group = log_record.alert_group
|
2024-07-09 11:23:53 -04:00
|
|
|
notification_policy = (
|
|
|
|
|
UserNotificationPolicy.get_default_fallback_policy(user)
|
|
|
|
|
if use_default_notification_policy_fallback
|
|
|
|
|
else log_record.notification_policy
|
|
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
notification_channel = notification_policy.notify_by if notification_policy else None
|
2024-07-09 11:23:53 -04:00
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
if user is None or notification_policy is None:
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
2024-10-10 17:37:30 +02:00
|
|
|
notification_policy=notification_policy if not use_default_notification_policy_fallback else None,
|
2022-06-03 08:09:47 -06:00
|
|
|
reason="Expected data is missing",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step if notification_policy else None,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=None,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2022-06-13 16:39:58 -06:00
|
|
|
if not user.is_notification_allowed:
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
2023-07-26 14:45:44 +01:00
|
|
|
reason="notification is not allowed for user",
|
2022-06-13 16:39:58 -06:00
|
|
|
alert_group=alert_group,
|
2022-11-29 09:41:56 +01:00
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_FORBIDDEN,
|
2022-06-13 16:39:58 -06:00
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2024-10-09 15:10:39 -03:00
|
|
|
if alert_group.resolved:
|
|
|
|
|
# skip notification if alert group was resolved
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
2024-10-10 17:37:30 +02:00
|
|
|
notification_policy=notification_policy if not use_default_notification_policy_fallback else None,
|
2024-10-09 15:10:39 -03:00
|
|
|
reason="Skipped notification because alert group is resolved",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step if notification_policy else None,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=None,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
if notification_channel == UserNotificationPolicy.NotificationChannel.SMS:
|
2023-05-24 14:27:48 +08:00
|
|
|
phone_backend = PhoneBackend()
|
|
|
|
|
phone_backend.notify_by_sms(user, alert_group, notification_policy)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
elif notification_channel == UserNotificationPolicy.NotificationChannel.PHONE_CALL:
|
2023-05-24 14:27:48 +08:00
|
|
|
phone_backend = PhoneBackend()
|
|
|
|
|
phone_backend.notify_by_call(user, alert_group, notification_policy)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
elif notification_channel == UserNotificationPolicy.NotificationChannel.TELEGRAM:
|
2024-01-24 16:31:56 +01:00
|
|
|
try:
|
|
|
|
|
TelegramToUserConnector.notify_user(user, alert_group, notification_policy)
|
|
|
|
|
except RetryAfter as e:
|
2024-10-15 10:35:54 -03:00
|
|
|
task_logger.exception(f"Telegram API rate limit exceeded. Retry after {e.retry_after} seconds.")
|
|
|
|
|
# check how much time has passed since log record was created
|
|
|
|
|
# to prevent eternal loop of restarting perform_notification task
|
|
|
|
|
if timezone.now() < log_record.created_at + timezone.timedelta(hours=RETRY_TIMEOUT_HOURS):
|
|
|
|
|
countdown = getattr(e, "retry_after", 3)
|
|
|
|
|
perform_notification.apply_async(
|
|
|
|
|
(log_record_pk, use_default_notification_policy_fallback), countdown=countdown
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
task_logger.debug(
|
|
|
|
|
f"telegram notification for alert_group {alert_group.pk} failed because of rate limit"
|
|
|
|
|
)
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
reason="Telegram rate limit exceeded",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_TELEGRAM_RATELIMIT,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
elif notification_channel == UserNotificationPolicy.NotificationChannel.SLACK:
|
|
|
|
|
# TODO: refactor checking the possibility of sending a notification in slack
|
|
|
|
|
# Code below is not consistent.
|
|
|
|
|
# We check various slack reasons to skip escalation in this task, in send_slack_notification,
|
|
|
|
|
# before and after posting of slack message.
|
2023-12-15 10:33:01 +01:00
|
|
|
if alert_group.skip_escalation_in_slack:
|
|
|
|
|
notification_error_code = UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK
|
|
|
|
|
if alert_group.reason_to_skip_escalation == alert_group.RATE_LIMITED:
|
|
|
|
|
notification_error_code = UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK_RATELIMIT
|
|
|
|
|
elif alert_group.reason_to_skip_escalation == alert_group.CHANNEL_ARCHIVED:
|
|
|
|
|
notification_error_code = (
|
|
|
|
|
UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK_CHANNEL_IS_ARCHIVED
|
|
|
|
|
)
|
|
|
|
|
elif alert_group.reason_to_skip_escalation == alert_group.ACCOUNT_INACTIVE:
|
|
|
|
|
notification_error_code = UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK_TOKEN_ERROR
|
2022-06-03 08:09:47 -06:00
|
|
|
task_logger.debug(
|
2023-12-15 10:33:01 +01:00
|
|
|
f"send_slack_notification for alert_group {alert_group.pk} failed because escalation in slack is "
|
|
|
|
|
f"skipped, reason: '{alert_group.get_reason_to_skip_escalation_display()}'"
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
2023-12-15 10:33:01 +01:00
|
|
|
reason=f"Skipped escalation in Slack, reason: '{alert_group.get_reason_to_skip_escalation_display()}'",
|
2022-06-03 08:09:47 -06:00
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
2023-12-15 10:33:01 +01:00
|
|
|
notification_error_code=notification_error_code,
|
2022-06-03 08:09:47 -06:00
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2023-12-18 13:13:18 -03:00
|
|
|
if alert_group.notify_in_slack_enabled is True:
|
2022-06-03 08:09:47 -06:00
|
|
|
# we cannot notify users in Slack if their team does not have Slack integration
|
|
|
|
|
if alert_group.channel.organization.slack_team_identity is None:
|
|
|
|
|
task_logger.debug(
|
|
|
|
|
f"send_slack_notification for alert_group {alert_group.pk} failed because slack team identity "
|
|
|
|
|
f"does not exist."
|
|
|
|
|
)
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
reason="Slack team identity does not exist",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK_TOKEN_ERROR,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2023-12-18 13:13:18 -03:00
|
|
|
if log_record.slack_prevent_posting:
|
|
|
|
|
task_logger.debug(
|
|
|
|
|
f"send_slack_notification for alert_group {alert_group.pk} failed because slack posting is disabled."
|
|
|
|
|
)
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
2024-11-20 10:14:14 -07:00
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_SUCCESS,
|
2023-12-18 13:13:18 -03:00
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
reason="Prevented from posting in Slack",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_POSTING_TO_SLACK_IS_DISABLED,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
|
2023-09-04 19:03:18 +01:00
|
|
|
if alert_group.slack_message:
|
|
|
|
|
alert_group.slack_message.send_slack_notification(user, alert_group, notification_policy)
|
2022-06-03 08:09:47 -06:00
|
|
|
task_logger.debug(f"Finished send_slack_notification for alert_group {alert_group.pk}.")
|
2024-11-26 06:03:38 -05:00
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
# check how much time has passed since log record was created
|
|
|
|
|
# to prevent eternal loop of restarting perform_notification task
|
2024-10-15 10:35:54 -03:00
|
|
|
elif timezone.now() < log_record.created_at + timezone.timedelta(hours=RETRY_TIMEOUT_HOURS):
|
2022-06-03 08:09:47 -06:00
|
|
|
task_logger.debug(
|
|
|
|
|
f"send_slack_notification for alert_group {alert_group.pk} failed because slack message "
|
|
|
|
|
f"does not exist. Restarting perform_notification."
|
|
|
|
|
)
|
|
|
|
|
restart_delay_seconds = 60
|
2024-07-09 11:23:53 -04:00
|
|
|
perform_notification.apply_async(
|
|
|
|
|
(log_record_pk, use_default_notification_policy_fallback), countdown=restart_delay_seconds
|
|
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
else:
|
|
|
|
|
task_logger.debug(
|
|
|
|
|
f"send_slack_notification for alert_group {alert_group.pk} failed because slack message "
|
2024-10-15 10:35:54 -03:00
|
|
|
f"after {RETRY_TIMEOUT_HOURS} hours still does not exist"
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
|
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
reason="Slack message does not exist",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_IN_SLACK,
|
|
|
|
|
).save()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
backend_id = UserNotificationPolicy.NotificationChannel(notification_policy.notify_by).name
|
|
|
|
|
backend = get_messaging_backend_from_id(backend_id)
|
|
|
|
|
except ValueError:
|
|
|
|
|
backend = None
|
|
|
|
|
|
|
|
|
|
if backend is None:
|
2023-07-26 14:45:44 +01:00
|
|
|
task_logger.debug("notify_user failed because messaging backend is not available")
|
2022-06-03 08:09:47 -06:00
|
|
|
UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
notification_policy=notification_policy,
|
|
|
|
|
reason="Messaging backend not available",
|
|
|
|
|
alert_group=alert_group,
|
|
|
|
|
notification_step=notification_policy.step,
|
|
|
|
|
notification_channel=notification_channel,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_MESSAGING_BACKEND_ERROR,
|
|
|
|
|
).save()
|
|
|
|
|
return
|
|
|
|
|
backend.notify_user(user, alert_group, notification_policy)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@shared_dedicated_queue_retry_task(
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
autoretry_for=(Exception,), retry_backoff=True, max_retries=1 if settings.DEBUG else None
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
def send_bundled_notification(user_notification_bundle_id: int):
|
|
|
|
|
"""
|
|
|
|
|
The task filters bundled notifications, attached to the current user_notification_bundle, by active alert groups,
|
|
|
|
|
creates notification log records and updates user_notification_bundle.
|
|
|
|
|
If there are no active alert groups - nothing else happens. If there is only one active alert group - regular
|
|
|
|
|
notification will be performed (called perform_notification task). Otherwise - "send bundled notification" method of
|
|
|
|
|
the current notification channel will be called.
|
|
|
|
|
"""
|
|
|
|
|
from apps.alerts.models import AlertGroup, UserNotificationBundle
|
|
|
|
|
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
|
2022-06-03 08:09:47 -06:00
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
task_logger.info(f"Start send_bundled_notification for user_notification_bundle {user_notification_bundle_id}")
|
|
|
|
|
with transaction.atomic():
|
|
|
|
|
try:
|
|
|
|
|
user_notification_bundle = UserNotificationBundle.objects.filter(
|
|
|
|
|
pk=user_notification_bundle_id
|
|
|
|
|
).select_for_update()[0]
|
|
|
|
|
except IndexError:
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"user_notification_bundle {user_notification_bundle_id} doesn't exist. "
|
|
|
|
|
f"The user associated with this notification bundle may have been deleted."
|
|
|
|
|
)
|
|
|
|
|
return
|
2023-07-25 10:43:23 +01:00
|
|
|
|
2024-11-29 08:21:29 -05:00
|
|
|
if send_bundled_notification.request.id != user_notification_bundle.notification_task_id:
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
task_logger.info(
|
|
|
|
|
f"send_bundled_notification: notification_task_id mismatch. "
|
|
|
|
|
f"Duplication or non-active notification triggered. "
|
|
|
|
|
f"Active: {user_notification_bundle.notification_task_id}"
|
|
|
|
|
)
|
|
|
|
|
return
|
2022-06-03 08:09:47 -06:00
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
notifications = user_notification_bundle.notifications.filter(bundle_uuid__isnull=True).select_related(
|
|
|
|
|
"alert_group"
|
|
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
log_records_to_create: typing.List["UserNotificationPolicyLogRecord"] = []
|
|
|
|
|
skip_notification_ids: typing.List[int] = []
|
|
|
|
|
active_alert_group_ids: typing.Set[int] = set()
|
|
|
|
|
log_record_notification_triggered = None
|
|
|
|
|
is_notification_allowed = user_notification_bundle.user.is_notification_allowed
|
2024-07-24 17:49:03 +02:00
|
|
|
bundle_uuid = uuid4()
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
|
|
|
|
|
# create logs
|
|
|
|
|
for notification in notifications:
|
|
|
|
|
if notification.alert_group.status != AlertGroup.NEW:
|
|
|
|
|
task_logger.info(f"alert_group {notification.alert_group_id} is not active, skip notification")
|
|
|
|
|
skip_notification_ids.append(notification.id)
|
|
|
|
|
continue
|
|
|
|
|
elif not is_notification_allowed:
|
|
|
|
|
log_record_notification_failed = UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user_notification_bundle.user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
|
|
|
|
reason="notification is not allowed for user",
|
|
|
|
|
alert_group=notification.alert_group,
|
|
|
|
|
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_FORBIDDEN,
|
|
|
|
|
)
|
|
|
|
|
log_records_to_create.append(log_record_notification_failed)
|
|
|
|
|
active_alert_group_ids.add(notification.alert_group_id)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# collect notifications for active alert groups
|
|
|
|
|
active_alert_group_ids.add(notification.alert_group_id)
|
|
|
|
|
|
|
|
|
|
log_record_notification_triggered = UserNotificationPolicyLogRecord(
|
|
|
|
|
author=user_notification_bundle.user,
|
|
|
|
|
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED,
|
|
|
|
|
alert_group=notification.alert_group,
|
2024-07-24 17:49:03 +02:00
|
|
|
notification_policy=notification.notification_policy,
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
notification_step=UserNotificationPolicy.Step.NOTIFY,
|
|
|
|
|
notification_channel=user_notification_bundle.notification_channel,
|
|
|
|
|
)
|
|
|
|
|
log_records_to_create.append(log_record_notification_triggered)
|
|
|
|
|
|
2024-07-24 17:49:03 +02:00
|
|
|
# delete non-active notifications and update bundle_uuid for the rest notifications
|
|
|
|
|
if not is_notification_allowed:
|
|
|
|
|
notifications.delete()
|
|
|
|
|
else:
|
|
|
|
|
notifications.filter(id__in=skip_notification_ids).delete()
|
|
|
|
|
notifications.update(bundle_uuid=bundle_uuid)
|
|
|
|
|
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
if len(log_records_to_create) == 1 and log_record_notification_triggered:
|
|
|
|
|
# perform regular notification
|
|
|
|
|
log_record_notification_triggered.save()
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"there is only one alert group in bundled notification, perform regular notification. "
|
|
|
|
|
f"alert_group {log_record_notification_triggered.alert_group_id}"
|
|
|
|
|
)
|
|
|
|
|
transaction.on_commit(
|
|
|
|
|
partial(
|
|
|
|
|
schedule_perform_notification_task,
|
|
|
|
|
log_record_notification_triggered.pk,
|
|
|
|
|
log_record_notification_triggered.alert_group_id,
|
2024-07-17 19:00:26 +02:00
|
|
|
False,
|
User notifications bundle (#4457)
# What this PR does
This PR adds two new models: UserNotificationBundle and
BundledNotification (proposals for naming are welcome).
`UserNotificationBundle` manages the information about last notification
time and scheduled notification task for bundled notifications. It is
unique per user + notification_channel + notification importance.
`BundledNotification` contains notification policy and alert group, that
triggered the notification. The BundledNotification instance is created
in `notify_user_task` for every notification, that should be bundled,
and is attached to UserNotificationBundle by ForeignKey connection.
How it works:
If the user was notified recently (within the last two minutes) by the
current notification channel, and this channel is bundlable,
BundledNotification instance will be created and attached to the
UserNotificationBundle instance, and `send_bundled_notification` task
will be scheduled to execute in 2 min.
In `send_bundled_notification` task we get all BundledNotification
attached to the current UserNotificationBundle instance, check if alert
groups are still active and if there is only one notification - perform
regular notification by calling `perform_notification` task, otherwise
call "notify_by_<channel>_bundle" method for the current notification
channel.
PR with method to send notification bundle by SMS -
https://github.com/grafana/oncall/pull/4624
**This feature is disabled by default by feature flag. Public docs will
be added in a separate PR with enabling this feature.**
## Which issue(s) this PR closes
related to https://github.com/grafana/oncall-private/issues/2712
## 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.
2024-07-16 13:24:08 +02:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
UserNotificationPolicyLogRecord.objects.bulk_create(log_records_to_create, batch_size=5000)
|
|
|
|
|
|
|
|
|
|
if not active_alert_group_ids or not is_notification_allowed:
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"no alert groups to notify about or notification is not allowed for user "
|
|
|
|
|
f"{user_notification_bundle.user_id}"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
task_logger.info(
|
|
|
|
|
f"perform bundled notification for alert groups with ids: {active_alert_group_ids}, "
|
|
|
|
|
f"bundle_uuid: {bundle_uuid}"
|
|
|
|
|
)
|
|
|
|
|
if user_notification_bundle.notification_channel == UserNotificationPolicy.NotificationChannel.SMS:
|
|
|
|
|
PhoneBackend.notify_by_sms_bundle_async(user_notification_bundle.user, bundle_uuid)
|
|
|
|
|
|
|
|
|
|
user_notification_bundle.notification_task_id = None
|
|
|
|
|
user_notification_bundle.last_notified_at = timezone.now()
|
|
|
|
|
user_notification_bundle.eta = None
|
|
|
|
|
user_notification_bundle.save(update_fields=["notification_task_id", "last_notified_at", "eta"])
|
|
|
|
|
|
|
|
|
|
for alert_group_id in active_alert_group_ids:
|
|
|
|
|
transaction.on_commit(partial(send_update_log_report_signal.apply_async, (None, alert_group_id)))
|
|
|
|
|
|
|
|
|
|
# update metric
|
|
|
|
|
transaction.on_commit(partial(update_metric_if_needed, user_notification_bundle.user, active_alert_group_ids))
|
|
|
|
|
|
|
|
|
|
task_logger.info(f"Finished send_bundled_notification for user_notification_bundle {user_notification_bundle_id}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# deprecated
|
|
|
|
|
@shared_dedicated_queue_retry_task(
|
|
|
|
|
autoretry_for=(Exception,), retry_backoff=True, max_retries=0 if settings.DEBUG else None
|
|
|
|
|
)
|
|
|
|
|
def send_user_notification_signal(log_record_pk):
|
|
|
|
|
# Triggers user_notification_action_triggered_signal
|
|
|
|
|
# This signal is only connected to UserSlackRepresentative and triggers posting message to Slack about some
|
|
|
|
|
# FAILED notifications (see NotificationDeliveryStep and ERRORS_TO_SEND_IN_SLACK_CHANNEL).
|
|
|
|
|
# No need to call it here.
|
|
|
|
|
pass
|