diff --git a/x-pack/plugins/alerting/server/usage/task_state.test.ts b/x-pack/plugins/alerting/server/usage/task_state.test.ts index 28d186b421cd4..f7286a1952d7a 100644 --- a/x-pack/plugins/alerting/server/usage/task_state.test.ts +++ b/x-pack/plugins/alerting/server/usage/task_state.test.ts @@ -174,4 +174,180 @@ describe('telemetry task state', () => { expect(result).not.toHaveProperty('foo'); }); }); + + describe('v2', () => { + const v2 = stateSchemaByVersion[2]; + it('should work on empty object when running the up migration', () => { + const result = v2.up({}); + expect(result).toMatchInlineSnapshot(` + Object { + "avg_es_search_duration_by_type_per_day": Object {}, + "avg_es_search_duration_per_day": 0, + "avg_execution_time_by_type_per_day": Object {}, + "avg_execution_time_per_day": 0, + "avg_total_search_duration_by_type_per_day": Object {}, + "avg_total_search_duration_per_day": 0, + "connectors_per_alert": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "count_active_by_type": Object {}, + "count_active_total": 0, + "count_alerts_by_rule_type": Object {}, + "count_alerts_total": 0, + "count_by_type": Object {}, + "count_connector_types_by_consumers": Object {}, + "count_disabled_total": 0, + "count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day": Object {}, + "count_failed_and_unrecognized_rule_tasks_by_status_per_day": Object {}, + "count_failed_and_unrecognized_rule_tasks_per_day": 0, + "count_mw_total": 0, + "count_mw_with_filter_alert_toggle_on": 0, + "count_mw_with_repeat_toggle_on": 0, + "count_rules_by_execution_status": Object { + "error": 0, + "success": 0, + "warning": 0, + }, + "count_rules_by_execution_status_per_day": Object {}, + "count_rules_by_notify_when": Object { + "on_action_group_change": 0, + "on_active_alert": 0, + "on_throttle_interval": 0, + }, + "count_rules_executions_by_type_per_day": Object {}, + "count_rules_executions_failured_by_reason_by_type_per_day": Object {}, + "count_rules_executions_failured_by_reason_per_day": Object {}, + "count_rules_executions_failured_per_day": 0, + "count_rules_executions_per_day": 0, + "count_rules_executions_timeouts_by_type_per_day": Object {}, + "count_rules_executions_timeouts_per_day": 0, + "count_rules_muted": 0, + "count_rules_namespaces": 0, + "count_rules_snoozed": 0, + "count_rules_with_muted_alerts": 0, + "count_rules_with_tags": 0, + "count_total": 0, + "error_messages": undefined, + "has_errors": false, + "percentile_num_alerts_by_type_per_day": Object {}, + "percentile_num_alerts_per_day": Object {}, + "percentile_num_generated_actions_by_type_per_day": Object {}, + "percentile_num_generated_actions_per_day": Object {}, + "runs": 0, + "schedule_time": Object { + "avg": "0s", + "max": "0s", + "min": "0s", + }, + "schedule_time_number_s": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "throttle_time": Object { + "avg": "0s", + "max": "0s", + "min": "0s", + }, + "throttle_time_number_s": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + } + `); + }); + + it(`shouldn't overwrite properties when running the up migration`, () => { + const state = { + avg_es_search_duration_by_type_per_day: { '.index-threshold': 1 }, + avg_es_search_duration_per_day: 2, + avg_execution_time_by_type_per_day: { '.index-threshold': 3 }, + avg_execution_time_per_day: 4, + avg_total_search_duration_by_type_per_day: { '.index-threshold': 5 }, + avg_total_search_duration_per_day: 6, + connectors_per_alert: { + avg: 7, + max: 8, + min: 9, + }, + count_active_by_type: { '.index-threshold': 10 }, + count_active_total: 11, + count_alerts_by_rule_type: {}, + count_alerts_total: 0, + count_by_type: { '.index-threshold': 12 }, + count_connector_types_by_consumers: { '.index-threshold': 13 }, + count_disabled_total: 14, + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: { + '.index-threshold': 15, + }, + count_failed_and_unrecognized_rule_tasks_by_status_per_day: { '.index-threshold': 16 }, + count_failed_and_unrecognized_rule_tasks_per_day: 17, + count_mw_total: 0, + count_mw_with_filter_alert_toggle_on: 0, + count_mw_with_repeat_toggle_on: 0, + count_rules_by_execution_status: { + error: 18, + success: 19, + warning: 20, + }, + count_rules_by_execution_status_per_day: { '.index-threshold': 21 }, + count_rules_by_notify_when: { + on_action_group_change: 22, + on_active_alert: 23, + on_throttle_interval: 24, + }, + count_rules_executions_by_type_per_day: { '.index-threshold': 25 }, + count_rules_executions_failured_by_reason_by_type_per_day: { '.index-threshold': 26 }, + count_rules_executions_failured_by_reason_per_day: { '.index-threshold': 27 }, + count_rules_executions_failured_per_day: 28, + count_rules_executions_per_day: 29, + count_rules_executions_timeouts_by_type_per_day: { '.index-threshold': 30 }, + count_rules_executions_timeouts_per_day: 31, + count_rules_muted: 32, + count_rules_namespaces: 33, + count_rules_snoozed: 34, + count_rules_with_muted_alerts: 35, + count_rules_with_tags: 36, + count_total: 37, + error_messages: ['foo'], + has_errors: true, + percentile_num_alerts_by_type_per_day: { '.index-threshold': 38 }, + percentile_num_alerts_per_day: { '.index-threshold': 39 }, + percentile_num_generated_actions_by_type_per_day: { '.index-threshold': 40 }, + percentile_num_generated_actions_per_day: { '.index-threshold': 41 }, + runs: 42, + schedule_time: { + avg: '43s', + max: '44s', + min: '45s', + }, + schedule_time_number_s: { + avg: 46, + max: 47, + min: 48, + }, + throttle_time: { + avg: '49s', + max: '50s', + min: '51s', + }, + throttle_time_number_s: { + avg: 52, + max: 53, + min: 54, + }, + }; + const result = v2.up(cloneDeep(state)); + expect(result).toEqual(state); + }); + + it('should drop unknown properties when running the up migration', () => { + const state = { foo: true }; + const result = v2.up(state); + expect(result).not.toHaveProperty('foo'); + }); + }); }); diff --git a/x-pack/plugins/alerting/server/usage/task_state.ts b/x-pack/plugins/alerting/server/usage/task_state.ts index ac9852b3dbace..3b33e540914ce 100644 --- a/x-pack/plugins/alerting/server/usage/task_state.ts +++ b/x-pack/plugins/alerting/server/usage/task_state.ts @@ -14,6 +14,112 @@ import { schema, TypeOf } from '@kbn/config-schema'; * As you add a new schema version, don't forget to change latestTaskStateSchema variable to reference the latest schema. * For example, changing stateSchemaByVersion[1].schema to stateSchemaByVersion[2].schema. */ + +const stateSchemaV1 = schema.object({ + has_errors: schema.boolean(), + error_messages: schema.maybe(schema.arrayOf(schema.any())), + runs: schema.number(), + count_total: schema.number(), + count_by_type: schema.recordOf(schema.string(), schema.number()), + throttle_time: schema.object({ + min: schema.string(), + avg: schema.string(), + max: schema.string(), + }), + schedule_time: schema.object({ + min: schema.string(), + avg: schema.string(), + max: schema.string(), + }), + throttle_time_number_s: schema.object({ + min: schema.number(), + avg: schema.number(), + max: schema.number(), + }), + schedule_time_number_s: schema.object({ + min: schema.number(), + avg: schema.number(), + max: schema.number(), + }), + connectors_per_alert: schema.object({ + min: schema.number(), + avg: schema.number(), + max: schema.number(), + }), + count_active_by_type: schema.recordOf(schema.string(), schema.number()), + count_active_total: schema.number(), + count_disabled_total: schema.number(), + count_rules_by_execution_status: schema.object({ + success: schema.number(), + error: schema.number(), + warning: schema.number(), + }), + count_rules_with_tags: schema.number(), + count_rules_by_notify_when: schema.object({ + on_action_group_change: schema.number(), + on_active_alert: schema.number(), + on_throttle_interval: schema.number(), + }), + count_rules_snoozed: schema.number(), + count_rules_muted: schema.number(), + count_rules_with_muted_alerts: schema.number(), + count_connector_types_by_consumers: schema.recordOf( + schema.string(), + schema.recordOf(schema.string(), schema.number()) + ), + count_rules_namespaces: schema.number(), + count_rules_executions_per_day: schema.number(), + count_rules_executions_by_type_per_day: schema.recordOf(schema.string(), schema.number()), + count_rules_executions_failured_per_day: schema.number(), + count_rules_executions_failured_by_reason_per_day: schema.recordOf( + schema.string(), + schema.number() + ), + count_rules_executions_failured_by_reason_by_type_per_day: schema.recordOf( + schema.string(), + schema.recordOf(schema.string(), schema.number()) + ), + count_rules_by_execution_status_per_day: schema.recordOf(schema.string(), schema.number()), + count_rules_executions_timeouts_per_day: schema.number(), + count_rules_executions_timeouts_by_type_per_day: schema.recordOf( + schema.string(), + schema.number() + ), + count_failed_and_unrecognized_rule_tasks_per_day: schema.number(), + count_failed_and_unrecognized_rule_tasks_by_status_per_day: schema.recordOf( + schema.string(), + schema.number() + ), + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: schema.recordOf( + schema.string(), + schema.recordOf(schema.string(), schema.number()) + ), + avg_execution_time_per_day: schema.number(), + avg_execution_time_by_type_per_day: schema.recordOf(schema.string(), schema.number()), + avg_es_search_duration_per_day: schema.number(), + avg_es_search_duration_by_type_per_day: schema.recordOf(schema.string(), schema.number()), + avg_total_search_duration_per_day: schema.number(), + avg_total_search_duration_by_type_per_day: schema.recordOf(schema.string(), schema.number()), + percentile_num_generated_actions_per_day: schema.recordOf(schema.string(), schema.number()), + percentile_num_generated_actions_by_type_per_day: schema.recordOf( + schema.string(), + schema.recordOf(schema.string(), schema.number()) + ), + percentile_num_alerts_per_day: schema.recordOf(schema.string(), schema.number()), + percentile_num_alerts_by_type_per_day: schema.recordOf( + schema.string(), + schema.recordOf(schema.string(), schema.number()) + ), +}); + +const stateSchemaV2 = stateSchemaV1.extends({ + count_mw_total: schema.number(), + count_mw_with_repeat_toggle_on: schema.number(), + count_mw_with_filter_alert_toggle_on: schema.number(), + count_alerts_total: schema.number(), + count_alerts_by_rule_type: schema.recordOf(schema.string(), schema.number()), +}); + export const stateSchemaByVersion = { 1: { // A task that was created < 8.10 will go through this "up" migration @@ -99,111 +205,22 @@ export const stateSchemaByVersion = { percentile_num_alerts_per_day: state.percentile_num_alerts_per_day || {}, percentile_num_alerts_by_type_per_day: state.percentile_num_alerts_by_type_per_day || {}, }), - schema: schema.object({ - has_errors: schema.boolean(), - error_messages: schema.maybe(schema.arrayOf(schema.any())), - runs: schema.number(), - count_total: schema.number(), - count_by_type: schema.recordOf(schema.string(), schema.number()), - throttle_time: schema.object({ - min: schema.string(), - avg: schema.string(), - max: schema.string(), - }), - schedule_time: schema.object({ - min: schema.string(), - avg: schema.string(), - max: schema.string(), - }), - throttle_time_number_s: schema.object({ - min: schema.number(), - avg: schema.number(), - max: schema.number(), - }), - schedule_time_number_s: schema.object({ - min: schema.number(), - avg: schema.number(), - max: schema.number(), - }), - connectors_per_alert: schema.object({ - min: schema.number(), - avg: schema.number(), - max: schema.number(), - }), - count_active_by_type: schema.recordOf(schema.string(), schema.number()), - count_active_total: schema.number(), - count_disabled_total: schema.number(), - count_rules_by_execution_status: schema.object({ - success: schema.number(), - error: schema.number(), - warning: schema.number(), - }), - count_rules_with_tags: schema.number(), - count_rules_by_notify_when: schema.object({ - on_action_group_change: schema.number(), - on_active_alert: schema.number(), - on_throttle_interval: schema.number(), - }), - count_rules_snoozed: schema.number(), - count_rules_muted: schema.number(), - count_mw_total: schema.number(), - count_mw_with_repeat_toggle_on: schema.number(), - count_mw_with_filter_alert_toggle_on: schema.number(), - count_rules_with_muted_alerts: schema.number(), - count_connector_types_by_consumers: schema.recordOf( - schema.string(), - schema.recordOf(schema.string(), schema.number()) - ), - count_rules_namespaces: schema.number(), - count_rules_executions_per_day: schema.number(), - count_rules_executions_by_type_per_day: schema.recordOf(schema.string(), schema.number()), - count_rules_executions_failured_per_day: schema.number(), - count_rules_executions_failured_by_reason_per_day: schema.recordOf( - schema.string(), - schema.number() - ), - count_rules_executions_failured_by_reason_by_type_per_day: schema.recordOf( - schema.string(), - schema.recordOf(schema.string(), schema.number()) - ), - count_rules_by_execution_status_per_day: schema.recordOf(schema.string(), schema.number()), - count_rules_executions_timeouts_per_day: schema.number(), - count_rules_executions_timeouts_by_type_per_day: schema.recordOf( - schema.string(), - schema.number() - ), - count_failed_and_unrecognized_rule_tasks_per_day: schema.number(), - count_failed_and_unrecognized_rule_tasks_by_status_per_day: schema.recordOf( - schema.string(), - schema.number() - ), - count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: schema.recordOf( - schema.string(), - schema.recordOf(schema.string(), schema.number()) - ), - avg_execution_time_per_day: schema.number(), - avg_execution_time_by_type_per_day: schema.recordOf(schema.string(), schema.number()), - avg_es_search_duration_per_day: schema.number(), - avg_es_search_duration_by_type_per_day: schema.recordOf(schema.string(), schema.number()), - avg_total_search_duration_per_day: schema.number(), - avg_total_search_duration_by_type_per_day: schema.recordOf(schema.string(), schema.number()), - percentile_num_generated_actions_per_day: schema.recordOf(schema.string(), schema.number()), - percentile_num_generated_actions_by_type_per_day: schema.recordOf( - schema.string(), - schema.recordOf(schema.string(), schema.number()) - ), - percentile_num_alerts_per_day: schema.recordOf(schema.string(), schema.number()), - percentile_num_alerts_by_type_per_day: schema.recordOf( - schema.string(), - schema.recordOf(schema.string(), schema.number()) - ), - count_alerts_total: schema.number(), - count_alerts_by_rule_type: schema.recordOf(schema.string(), schema.number()), + schema: stateSchemaV1, + }, + 2: { + up: (state: Record) => ({ + ...stateSchemaByVersion[1].up(state), + count_mw_total: state.count_mw_total || 0, + count_mw_with_repeat_toggle_on: state.count_mw_with_repeat_toggle_on || 0, + count_mw_with_filter_alert_toggle_on: state.count_mw_with_filter_alert_toggle_on || 0, + count_alerts_total: state.count_alerts_total || 0, + count_alerts_by_rule_type: state.count_alerts_by_rule_type || {}, }), + schema: stateSchemaV2, }, }; -const latestTaskStateSchema = stateSchemaByVersion[1].schema; +const latestTaskStateSchema = stateSchemaByVersion[2].schema; export type LatestTaskStateSchema = TypeOf; export const emptyState: LatestTaskStateSchema = {