diff --git a/public/app/features/alerting/unified/Analytics.ts b/public/app/features/alerting/unified/Analytics.ts new file mode 100644 index 00000000000..586617926a8 --- /dev/null +++ b/public/app/features/alerting/unified/Analytics.ts @@ -0,0 +1,5 @@ +export const LogMessages = { + filterByLabel: 'filtering alert instances by label', + loadedList: 'loaded Alert Rules list', + leavingRuleGroupEdit: 'leaving rule group edit without saving', +}; diff --git a/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.test.tsx b/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.test.tsx new file mode 100644 index 00000000000..ca59051e704 --- /dev/null +++ b/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.test.tsx @@ -0,0 +1,25 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import lodash from 'lodash'; // eslint-disable-line lodash/import-scope +import React from 'react'; + +import { logInfo } from '@grafana/runtime'; + +import { LogMessages } from '../../Analytics'; + +import { MatcherFilter } from './MatcherFilter'; + +jest.mock('@grafana/runtime'); + +describe('Analytics', () => { + it('Sends log info when filtering alert instances by label', async () => { + lodash.debounce = jest.fn().mockImplementation((fn) => fn); + + render(); + + const searchInput = screen.getByTestId('search-query-input'); + await userEvent.type(searchInput, 'job='); + + expect(logInfo).toHaveBeenCalledWith(LogMessages.filterByLabel); + }); +}); diff --git a/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.tsx b/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.tsx index f885fdbea8b..6eebd413c22 100644 --- a/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.tsx +++ b/public/app/features/alerting/unified/components/alert-groups/MatcherFilter.tsx @@ -1,9 +1,13 @@ import { css } from '@emotion/css'; +import { debounce } from 'lodash'; import React, { FormEvent } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; +import { logInfo } from '@grafana/runtime'; import { Label, Tooltip, Input, Icon, useStyles2, Stack } from '@grafana/ui'; +import { LogMessages } from '../../Analytics'; + interface Props { className?: string; queryString?: string; @@ -13,10 +17,12 @@ interface Props { export const MatcherFilter = ({ className, onFilterChange, defaultQueryString, queryString }: Props) => { const styles = useStyles2(getStyles); - const handleSearchChange = (e: FormEvent) => { + const handleSearchChange = debounce((e: FormEvent) => { + logInfo(LogMessages.filterByLabel); + const target = e.target as HTMLInputElement; onFilterChange(target.value); - }; + }, 600); const searchIcon = ; return (
diff --git a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx index f2650b72f94..ef6f901cf31 100644 --- a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx +++ b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx @@ -18,7 +18,7 @@ import { EvaluationIntervalLimitExceeded } from '../InvalidIntervalWarning'; interface ModalProps { namespace: CombinedRuleNamespace; group: CombinedRuleGroup; - onClose: () => void; + onClose: (saved?: boolean) => void; } interface FormValues { @@ -46,7 +46,7 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement { // close modal if successfully saved useEffect(() => { if (dispatched && !loading && !error) { - onClose(); + onClose(true); } }, [dispatched, loading, onClose, error]); @@ -123,7 +123,13 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement { )} -