Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

User notifications bundle #4457

Merged
merged 32 commits into from
Jul 16, 2024
Merged

User notifications bundle #4457

merged 32 commits into from
Jul 16, 2024

Conversation

Ferril
Copy link
Member

@Ferril Ferril commented Jun 4, 2024

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__bundle" method for the current notification channel.

PR with method to send notification bundle by SMS - #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

  • Unit, integration, and e2e (if applicable) tests updated
  • Documentation added (or pr:no public docs PR label added if not required)
  • 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.

@Ferril Ferril temporarily deployed to github-pages June 4, 2024 12:37 — with GitHub Actions Inactive
@Ferril Ferril temporarily deployed to github-pages June 4, 2024 13:03 — with GitHub Actions Inactive
@Ferril Ferril temporarily deployed to github-pages June 7, 2024 13:14 — with GitHub Actions Inactive
@Ferril Ferril temporarily deployed to github-pages June 7, 2024 13:27 — with GitHub Actions Inactive
notification_channel=notification_policy.notify_by,
)
# todo: feature flag
if notification_policy.notify_by in UserNotificationBundle.NOTIFICATION_CHANNELS_TO_BUNDLE:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: worth to make is_bundlable method for user_notification_policy

@Ferril Ferril added release:patch PR will be added to "Other Changes" section of release notes pr:no public docs Added to a PR that does not require public documentation updates labels Jul 8, 2024
@Ferril Ferril temporarily deployed to github-pages July 8, 2024 16:08 — with GitHub Actions Inactive
@Ferril Ferril marked this pull request as ready for review July 8, 2024 16:12
@Ferril Ferril requested a review from a team July 8, 2024 16:12
@@ -16,3 +16,7 @@ class UserHasNotification(models.Model):

class Meta:
unique_together = ("user", "alert_group")

def update_active_task_id(self, task_id):
self.active_notification_policy_id = task_id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe out of scope for this PR but I think this model should be renamed to something like UserActiveNotificationPolicy (UserHasNotification isn't very informative imo 😬 )

if next_notification_policy.notify_by not in collected_steps_ids:
collected_steps_ids.append(next_notification_policy.notify_by)

reason = build_notification_reason_for_log_record(notification_policies, reason)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! slowly breaks apart this function 🙂

engine/apps/alerts/tasks/notify_user.py Outdated Show resolved Hide resolved
notification_step=notification_policy.step,
notification_channel=notification_policy.notify_by,
)
if (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

engine/apps/alerts/tasks/notify_user.py Show resolved Hide resolved
engine/apps/alerts/tasks/notify_user.py Show resolved Hide resolved
Copy link
Contributor

@joeyorlando joeyorlando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall LGTM!

engine/apps/alerts/tasks/notify_user.py Outdated Show resolved Hide resolved
engine/apps/alerts/tasks/notify_user.py Outdated Show resolved Hide resolved
engine/apps/alerts/tasks/notify_user.py Show resolved Hide resolved
engine/apps/alerts/tasks/notify_user.py Outdated Show resolved Hide resolved
engine/apps/alerts/models/user_notification_bundle.py Outdated Show resolved Hide resolved
UserNotificationBundle, on_delete=models.CASCADE, related_name="notifications"
)
created_at = models.DateTimeField(auto_now_add=True)
bundle_uuid = models.CharField(max_length=100, null=True, default=None, db_index=True)
Copy link
Contributor

@joeyorlando joeyorlando Jul 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is primarly used right now in as the second arg to PhoneBackend.notify_by_sms_bundle_async, but can we just use pk instead of needing also bundle_uuid, or is there a need for a UUID?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that bundle_uuid groups a bunch of BundledNotifications, that were processed in the send_bundled_notification task (if user got flooded, it can be a hundreds of them). While we are processing these notifications, new notifications can be created and attached to the current UserNotificationBundle and they will have their own bundle_uuid and will be processed and sent in a separate task.
That means, that we can't use UserNotificationBundle pk, because there could be processed and unprocessed notifications attached at the same time, and we want to keep them separately. We don't want to use BundledNotification pks, because there could be a long list of them

engine/apps/alerts/tasks/notify_user.py Outdated Show resolved Hide resolved
Ferril added 4 commits July 9, 2024 14:50
# Conflicts:
#	engine/apps/alerts/tasks/notify_user.py
#	engine/apps/alerts/tests/test_notify_user.py
@Ferril Ferril added this pull request to the merge queue Jul 16, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jul 16, 2024
@Ferril Ferril added this pull request to the merge queue Jul 16, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jul 16, 2024
@Ferril Ferril added this pull request to the merge queue Jul 16, 2024
Merged via the queue into dev with commit 191814b Jul 16, 2024
21 checks passed
@Ferril Ferril deleted the user-notification-bundle branch July 16, 2024 11:33
github-merge-queue bot pushed a commit that referenced this pull request Jul 16, 2024
# What this PR does
Adds method to render and send notification bundle by sms.

Example of SMS message:
```
Grafana OnCall: Alert groups #1, #2, #3 and 2 more 
from stack: TestOrganization, 
integrations: Grafana Alerting and 1 more.
```

Should be merged with #4457

## Which issue(s) this PR closes
grafana/oncall-private#2713

## 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:no public docs Added to a PR that does not require public documentation updates release:patch PR will be added to "Other Changes" section of release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants