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

[RAM] Add data model for scheduled and recurring snoozes #131019

Merged
merged 60 commits into from
May 18, 2022

Conversation

Zacqary
Copy link
Contributor

@Zacqary Zacqary commented Apr 26, 2022

Summary

Closes #130724

Migrates the data model for rules from muteAll/snoozeEndTime to snoozeIndefinitely/snoozeSchedule.

snoozeIndefinitely is a straight rename of muteAll and functions the same way. (Removed this as it's too large of a code change; muteAll is used in a ton of places)

snoozeSchedule is an array of scheduled snooze times, including options for recurring on a time interval or certain days of the week. Recurrence is formatted in the form of an iCal RRULE, and this PR adds the rrule package to parse these. Also adds luxon which is its required peer dependency for dealing with time zones.

This just changes the data model and the task manager's parsing of it. APIs and UIs remain broadly unchanged for now.

The only change to the APIs and UIs are the addition of an is_snoozed_until property in the API response. This property is identical to the previously existing snooze_end_time, but it gets derived on the server side from the snooze schedule using the getRuleSnoozeEndTime function. The reason we do this is because making the rrule package available in the frontend balloons the alerting plugin size, so all RRULE parsing needs to happen on the server. This may not last, as we're eventually going to need to generate RRULE strings from the snooze UI, but I don't want to include the decision to increase the alerting bundle size in this PR.

UPDATE 5/12: To aid in filtering, isSnoozedUntil will now be stored in the SavedObject. This property is computed and added to the SavedObject either when the _snooze API is called (for snoozes that start as soon as they're added), OR when the task runner attempts to execute the rule (for recurring snoozes). As far as the task runner is concerned, the actual snooze source of truth will always be the snoozeSchedule. isSnoozedUntil will purely be for display and sorting.

UPDATE 5/16: Closes #132164 and uses rRule even for simple snoozes. When the user clicks "Snooze for 3 days" this will now set a snooze with an rRule of { dtstart: NOW, count: 1 }

Checklist

Zacqary added 3 commits April 26, 2022 15:16
…-datamodel

# Conflicts:
#	x-pack/plugins/alerting/server/saved_objects/migrations.ts
#	x-pack/plugins/alerting/server/task_runner/task_runner.ts
@Zacqary Zacqary added release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) Feature:Alerting/RulesManagement Issues related to the Rules Management UX v8.3.0 labels Apr 26, 2022
Zacqary added 5 commits May 11, 2022 15:11
…-datamodel

# Conflicts:
#	x-pack/plugins/alerting/server/lib/index.ts
#	x-pack/plugins/alerting/server/routes/find_rules.ts
#	x-pack/plugins/alerting/server/rules_client/rules_client.ts
@Zacqary
Copy link
Contributor Author

Zacqary commented May 12, 2022

Updated the description with this but reposting here:

To aid in filtering, isSnoozedUntil will now be stored in the SavedObject. This property is computed and added to the SavedObject either when the _snooze API is called (for snoozes that start as soon as they're added), OR when the task runner attempts to execute the rule (for recurring snoozes). As far as the task runner is concerned, the actual snooze source of truth will always be the snoozeSchedule. isSnoozedUntil will purely be for display and sorting.

Copy link
Member

@pmuellr pmuellr left a comment

Choose a reason for hiding this comment

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

Added some comments. It feels like we have too many combinations of properties that can be used to define "mute all forever", "mute all with a duration", and the eventual rRule-based snoozes. Wondering if we can boil this down to a simpler set of properties, where we ALWAYS have an rRule in place.

I could totally believe we can't! I just need to be convinced.

And I think we need a bit of doc in the rule_snooze_type module describing these properties, as well as some doc in the PR describing all the combinations of things that can happen today, with an hint of how we plan on dealing with rRule schedules in the future.

yarn.lock Outdated Show resolved Hide resolved
@@ -2817,3 +2860,9 @@ function parseDate(dateString: string | undefined, propertyName: string, default

return parsedDate;
}

function clearUnscheduledSnooze(attributes: { snoozeSchedule?: RuleSnooze }) {
Copy link
Member

Choose a reason for hiding this comment

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

Not completely clear what this function is doing, but I think it's removing "mute all" snoozes that have a duration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not exactly. This clears any "simple" snoozes, i.e. the user selects "Snooze for 3 days (starting now)" in the currently-existing UX, instead of e.g. "Snooze on Friday for 3 days" or "Snooze every Friday for 3 days" as made possible by the new functionality. It's the functional equivalent of setting snoozeEndTime: null in the previous version of the data model.

Copy link
Member

Choose a reason for hiding this comment

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

Ah ... somehow we need to get all this documented, at least for ourselves. Doesn't need to be this PR though, in the spirit of time. I added a request to add doc to #132266 ...

Copy link
Member

@pmuellr pmuellr left a comment

Choose a reason for hiding this comment

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

LGTM; noted some things for follow ups - more doc (somewhere) and more robust parsing for the wacky day-of-week with optional numeric suffix thing (probably could be made into a grep pattern).

@@ -2817,3 +2860,9 @@ function parseDate(dateString: string | undefined, propertyName: string, default

return parsedDate;
}

function clearUnscheduledSnooze(attributes: { snoozeSchedule?: RuleSnooze }) {
Copy link
Member

Choose a reason for hiding this comment

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

Ah ... somehow we need to get all this documented, at least for ourselves. Doesn't need to be this PR though, in the spirit of time. I added a request to add doc to #132266 ...

function parseByWeekday(byweekday: Array<string | number>): ByWeekday[] {
return byweekday.map((w) => {
if (typeof w === 'number') return w;
if (['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].includes(w)) return w as WeekdayStr;
Copy link
Member

Choose a reason for hiding this comment

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

nit: you could create a const Set for these strings at the top-level, and then just use WeekdaySet.has(w)

return byweekday.map((w) => {
if (typeof w === 'number') return w;
if (['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].includes(w)) return w as WeekdayStr;
const dayOfWeek = w.slice(-2) as WeekdayStr;
Copy link
Member

Choose a reason for hiding this comment

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

Feels like we may need a more robust parser for these BYDAY values - I had to look it up to make sure I was understanding this code :-). Who proposed using this wacky format!!! :-). https://icalendar.org/iCalendar-RFC-5545/3-3-10-recurrence-rule.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah unfortunately the rrule library will parse an entire rrule string, but not just a segment of it, so we can't rely on its already robust parsing of BYDAY. I added a comment though.

Copy link
Member

Choose a reason for hiding this comment

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

Not that we need to do it for this PR, but could we construct a legal but fake rRule with the BYDAY value, then send it to the rRule parser to just extract the relevant fields?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh wait actually yeah that does work

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, may have spoken too soon, the parsed RRule object only seems to return its byweekday in the form of an array of numbers, and I'm not sure how to extract an nth day of week from it. Still playing with it though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops nevermind had to use origOptions, this works fine

@Zacqary Zacqary enabled auto-merge (squash) May 18, 2022 00:42
@Zacqary Zacqary disabled auto-merge May 18, 2022 15:48
@Zacqary Zacqary enabled auto-merge (squash) May 18, 2022 15:59
@Zacqary Zacqary merged commit 64689c0 into elastic:main May 18, 2022
@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
alerting 26 27 +1

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
alerting 330 349 +19

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
triggersActionsUi 782.0KB 782.0KB +57.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
triggersActionsUi 103.9KB 103.9KB +38.0B

Saved Objects .kibana field count

Every field in each saved object type adds overhead to Elasticsearch. Kibana needs to keep the total field count below Elasticsearch's default limit of 1000 fields. Only specify field mappings for the fields you wish to search on or query. See https://www.elastic.co/guide/en/kibana/master/development-plugin-saved-objects.html#_mappings

id before after diff
alert 54 74 +20
Unknown metric groups

API count

id before after diff
alerting 339 358 +19

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label May 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Alerting/RulesManagement Issues related to the Rules Management UX release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v8.3.0
Projects
None yet
9 participants