Browse Source

feat(issue-alert): incompatible rules/test notification analytics (#42122)

Records analytics for when an incompatible rule is found and when a test
notification is sent
Andrew Xue 2 years ago
parent
commit
038fcda2af

+ 4 - 0
static/app/utils/analytics/workflowAnalyticsEvents.tsx

@@ -47,6 +47,8 @@ export type TeamInsightsEventParameters = {
     project_id: string;
     type: string;
   };
+  'edit_alert_rule.incompatible_rule': {};
+  'edit_alert_rule.notification_test': {success: boolean};
   'edit_alert_rule.viewed': RuleViewed;
   'issue_alert_rule_details.edit_clicked': {rule_id: number};
   'issue_alert_rule_details.viewed': {rule_id: number};
@@ -102,6 +104,8 @@ export const workflowEventMap: Record<TeamInsightsEventKey, string | null> = {
   'alert_wizard.option_viewed': 'Alert Wizard: Option Viewed',
   'edit_alert_rule.add_row': 'Edit Alert Rule: Add Row',
   'edit_alert_rule.viewed': 'Edit Alert Rule: Viewed',
+  'edit_alert_rule.incompatible_rule': 'Edit Alert Rule: Incompatible Rule',
+  'edit_alert_rule.notification_test': 'Edit Alert Rule: Notification Test',
   'issue_alert_rule_details.edit_clicked': 'Issue Alert Rule Details: Edit Clicked',
   'issue_alert_rule_details.viewed': 'Issue Alert Rule Details: Viewed',
   'issue_details.action_clicked': 'Issue Details: Action Clicked',

+ 21 - 3
static/app/views/alerts/rules/issue/index.tsx

@@ -173,6 +173,7 @@ function isSavedAlertRule(rule: State['rule']): rule is IssueAlertRule {
 
 class IssueRuleEditor extends AsyncView<Props, State> {
   pollingTimeout: number | undefined = undefined;
+  trackIncompatibleAnalytics: boolean = false;
 
   get isDuplicateRule(): boolean {
     const {location} = this.props;
@@ -432,10 +433,19 @@ class IssueRuleEditor extends AsyncView<Props, State> {
   // As more incompatible combinations are added, we will need a more generic way to check for incompatibility.
   checkIncompatibleRule = debounce(() => {
     if (this.props.organization.features.includes('issue-alert-incompatible-rules')) {
-      const incompatibleRule = findIncompatibleRules(this.state.rule);
+      const {conditionIndices, filterIndices} = findIncompatibleRules(this.state.rule);
+      if (
+        !this.trackIncompatibleAnalytics &&
+        (conditionIndices !== null || filterIndices !== null)
+      ) {
+        this.trackIncompatibleAnalytics = true;
+        trackAdvancedAnalyticsEvent('edit_alert_rule.incompatible_rule', {
+          organization: this.props.organization,
+        });
+      }
       this.setState({
-        incompatibleConditions: incompatibleRule.conditionIndices,
-        incompatibleFilters: incompatibleRule.filterIndices,
+        incompatibleConditions: conditionIndices,
+        incompatibleFilters: filterIndices,
       });
     }
   }, 500);
@@ -492,9 +502,17 @@ class IssueRuleEditor extends AsyncView<Props, State> {
       })
       .then(() => {
         addSuccessMessage(tn('Notification sent!', 'Notifications sent!', actions));
+        trackAdvancedAnalyticsEvent('edit_alert_rule.notification_test', {
+          organization,
+          success: true,
+        });
       })
       .catch(() => {
         addErrorMessage(tn('Notification failed', 'Notifications failed', actions));
+        trackAdvancedAnalyticsEvent('edit_alert_rule.notification_test', {
+          organization,
+          success: false,
+        });
       })
       .finally(() => {
         this.setState({sendingNotification: false});