From e3805e13095eac7191c1876d1dd0070b06c8b373 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Wed, 14 Dec 2022 11:50:15 -0300 Subject: [PATCH] Alerting: Track events for rule creation/abortion (#59912) * Track events for rule creation/abortion These events will be sent to Rudderstack using the EchoSrv in order to be consumed from Intercom * Change method names and send user_id * Track validation errors * Only track errors for rule creation --- .../features/alerting/unified/Analytics.ts | 20 ++++++++++++- .../components/rule-editor/AlertRuleForm.tsx | 30 +++++++++++++++---- .../alerting/unified/state/actions.ts | 13 ++++++-- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/public/app/features/alerting/unified/Analytics.ts b/public/app/features/alerting/unified/Analytics.ts index 62eb16a5628..e872a66a960 100644 --- a/public/app/features/alerting/unified/Analytics.ts +++ b/public/app/features/alerting/unified/Analytics.ts @@ -1,5 +1,5 @@ import { faro, LogLevel as GrafanaLogLevel } from '@grafana/faro-web-sdk'; -import { config } from '@grafana/runtime/src'; +import { config, reportInteraction } from '@grafana/runtime/src'; export const LogMessages = { filterByLabel: 'filtering alert instances by label', @@ -39,3 +39,21 @@ export function withPerformanceLogging Promise return response; }; } + +export const trackNewAlerRuleFormSaved = (props: AlertRuleTrackingProps) => { + reportInteraction('grafana_alerting_rule_creation', props); +}; + +export const trackNewAlerRuleFormCancelled = (props: AlertRuleTrackingProps) => { + reportInteraction('grafana_alerting_rule_aborted', props); +}; + +export const trackNewAlerRuleFormError = (props: AlertRuleTrackingProps & { error: string }) => { + reportInteraction('grafana_alerting_rule_form_error', props); +}; + +export type AlertRuleTrackingProps = { + grafana_version?: string; + org_id?: number; + user_id?: number; +}; diff --git a/public/app/features/alerting/unified/components/rule-editor/AlertRuleForm.tsx b/public/app/features/alerting/unified/components/rule-editor/AlertRuleForm.tsx index f08b9a371af..26e1dfec4bc 100644 --- a/public/app/features/alerting/unified/components/rule-editor/AlertRuleForm.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/AlertRuleForm.tsx @@ -1,18 +1,19 @@ import { css } from '@emotion/css'; import React, { FC, useMemo, useState } from 'react'; -import { FormProvider, useForm, useFormContext, UseFormWatch } from 'react-hook-form'; +import { DeepMap, FieldError, FormProvider, useForm, useFormContext, UseFormWatch } from 'react-hook-form'; import { Link } from 'react-router-dom'; import { GrafanaTheme2 } from '@grafana/data'; -import { logInfo } from '@grafana/runtime'; +import { logInfo, config } from '@grafana/runtime'; import { Button, ConfirmModal, CustomScrollbar, Spinner, useStyles2, HorizontalGroup, Field, Input } from '@grafana/ui'; import { useAppNotification } from 'app/core/copy/appNotification'; +import { contextSrv } from 'app/core/core'; import { useCleanup } from 'app/core/hooks/useCleanup'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { useDispatch } from 'app/types'; import { RuleWithLocation } from 'app/types/unified-alerting'; -import { LogMessages } from '../../Analytics'; +import { LogMessages, trackNewAlerRuleFormCancelled, trackNewAlerRuleFormError } from '../../Analytics'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { deleteRuleAction, saveRuleFormAction } from '../../state/actions'; import { RuleFormType, RuleFormValues } from '../../types/rule-form'; @@ -157,10 +158,29 @@ export const AlertRuleForm: FC = ({ existing, prefill }) => { } }; - const onInvalid = () => { + const onInvalid = (errors: DeepMap): void => { + if (!existing) { + trackNewAlerRuleFormError({ + grafana_version: config.buildInfo.version, + org_id: contextSrv.user.orgId, + user_id: contextSrv.user.id, + error: Object.keys(errors).toString(), + }); + } notifyApp.error('There are errors in the form. Please correct them and try again!'); }; + const cancelRuleCreation = () => { + logInfo(LogMessages.cancelSavingAlertRule); + if (!existing) { + trackNewAlerRuleFormCancelled({ + grafana_version: config.buildInfo.version, + org_id: contextSrv.user.orgId, + user_id: contextSrv.user.id, + }); + } + }; + return (
e.preventDefault()} className={styles.form}> @@ -171,7 +191,7 @@ export const AlertRuleForm: FC = ({ existing, prefill }) => { disabled={submitState.loading} type="button" fill="outline" - onClick={() => logInfo(LogMessages.cancelSavingAlertRule)} + onClick={cancelRuleCreation} > Cancel diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts index 187983368b1..979307bed6a 100644 --- a/public/app/features/alerting/unified/state/actions.ts +++ b/public/app/features/alerting/unified/state/actions.ts @@ -1,7 +1,7 @@ import { createAsyncThunk, AsyncThunk } from '@reduxjs/toolkit'; import { isEmpty } from 'lodash'; -import { locationService } from '@grafana/runtime'; +import { locationService, config } from '@grafana/runtime'; import { AlertmanagerAlert, AlertManagerCortexConfig, @@ -31,8 +31,9 @@ import { RulerRulesConfigDTO, } from 'app/types/unified-alerting-dto'; +import { contextSrv } from '../../../../core/core'; import { backendSrv } from '../../../../core/services/backend_srv'; -import { logInfo, LogMessages, withPerformanceLogging } from '../Analytics'; +import { logInfo, LogMessages, withPerformanceLogging, trackNewAlerRuleFormSaved } from '../Analytics'; import { addAlertManagers, createOrUpdateSilence, @@ -485,6 +486,14 @@ export const saveRuleFormAction = createAsyncThunk( logInfo(LogMessages.successSavingAlertRule); + if (!existing) { + trackNewAlerRuleFormSaved({ + grafana_version: config.buildInfo.version, + org_id: contextSrv.user.orgId, + user_id: contextSrv.user.id, + }); + } + if (redirectOnSave) { locationService.push(redirectOnSave); } else {