diff --git a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx index 83b73403dc8..7a450f373a0 100644 --- a/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryCard.test.tsx @@ -18,6 +18,11 @@ const mockDS = mockDataSource({ type: DataSourceType.Alertmanager, }); +jest.mock('@grafana/runtime', () => ({ + ...jest.requireActual('@grafana/runtime'), + reportInteraction: jest.fn(), +})); + jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => { return { getDataSourceSrv: () => ({ diff --git a/public/app/features/explore/RichHistory/RichHistoryCard.tsx b/public/app/features/explore/RichHistory/RichHistoryCard.tsx index 850c46f9ee8..df3efab5bde 100644 --- a/public/app/features/explore/RichHistory/RichHistoryCard.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryCard.tsx @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { GrafanaTheme, DataSourceApi, DataQuery } from '@grafana/data'; -import { getDataSourceSrv } from '@grafana/runtime'; +import { config, getDataSourceSrv, reportInteraction } from '@grafana/runtime'; import { stylesFactory, useTheme, TextArea, Button, IconButton } from '@grafana/ui'; import { notifyApp } from 'app/core/actions'; import appEvents from 'app/core/app_events'; @@ -176,12 +176,17 @@ export function RichHistoryCard(props: Props) { const onRunQuery = async () => { const queriesToRun = query.queries; - if (query.datasourceName !== datasourceInstance?.name) { + const differentDataSource = query.datasourceName !== datasourceInstance?.name; + if (differentDataSource) { await changeDatasource(exploreId, query.datasourceName, { importQueries: true }); setQueries(exploreId, queriesToRun); } else { setQueries(exploreId, queriesToRun); } + reportInteraction('grafana_explore_query_history_run', { + queryHistoryEnabled: config.queryHistoryEnabled, + differentDataSource, + }); }; const onCopyQuery = () => { @@ -196,6 +201,14 @@ export function RichHistoryCard(props: Props) { }; const onDeleteQuery = () => { + const performDelete = (queryId: string) => { + deleteHistoryItem(queryId); + dispatch(notifyApp(createSuccessNotification('Query deleted'))); + reportInteraction('grafana_explore_query_history_deleted', { + queryHistoryEnabled: config.queryHistoryEnabled, + }); + }; + // For starred queries, we want confirmation. For non-starred, we don't. if (query.starred) { appEvents.publish( @@ -204,20 +217,20 @@ export function RichHistoryCard(props: Props) { text: 'Are you sure you want to permanently delete your starred query?', yesText: 'Delete', icon: 'trash-alt', - onConfirm: () => { - deleteHistoryItem(query.id); - dispatch(notifyApp(createSuccessNotification('Query deleted'))); - }, + onConfirm: () => performDelete(query.id), }) ); } else { - deleteHistoryItem(query.id); - dispatch(notifyApp(createSuccessNotification('Query deleted'))); + performDelete(query.id); } }; const onStarrQuery = () => { starHistoryItem(query.id, !query.starred); + reportInteraction('grafana_explore_query_history_starred', { + queryHistoryEnabled: config.queryHistoryEnabled, + newValue: !query.starred, + }); }; const toggleActiveUpdateComment = () => setActiveUpdateComment(!activeUpdateComment); @@ -225,6 +238,9 @@ export function RichHistoryCard(props: Props) { const onUpdateComment = () => { commentHistoryItem(query.id, comment); setActiveUpdateComment(false); + reportInteraction('grafana_explore_query_history_commented', { + queryHistoryEnabled: config.queryHistoryEnabled, + }); }; const onCancelUpdateComment = () => { diff --git a/public/app/features/explore/RichHistory/RichHistoryContainer.test.tsx b/public/app/features/explore/RichHistory/RichHistoryContainer.test.tsx index dfe279eca66..84d1aca02a9 100644 --- a/public/app/features/explore/RichHistory/RichHistoryContainer.test.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryContainer.test.tsx @@ -17,6 +17,7 @@ jest.mock('@grafana/runtime', () => ({ getList: () => [], }; }, + reportInteraction: jest.fn(), })); const setup = (propOverrides?: Partial) => { diff --git a/public/app/features/explore/RichHistory/RichHistoryContainer.tsx b/public/app/features/explore/RichHistory/RichHistoryContainer.tsx index 099cea64304..72fb7c125f1 100644 --- a/public/app/features/explore/RichHistory/RichHistoryContainer.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryContainer.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import { config, reportInteraction } from '@grafana/runtime'; import { useTheme2 } from '@grafana/ui'; // Types import { ExploreItemState, StoreState } from 'app/types'; @@ -86,6 +87,9 @@ export function RichHistoryContainer(props: Props) { useEffect(() => { initRichHistory(); + reportInteraction('grafana_explore_query_history_opened', { + queryHistoryEnabled: config.queryHistoryEnabled, + }); }, [initRichHistory]); if (!richHistorySettings) { diff --git a/public/app/features/explore/spec/queryHistory.test.tsx b/public/app/features/explore/spec/queryHistory.test.tsx index 9bcc796adf7..682b1913ac4 100644 --- a/public/app/features/explore/spec/queryHistory.test.tsx +++ b/public/app/features/explore/spec/queryHistory.test.tsx @@ -40,9 +40,13 @@ import { const fetchMock = jest.fn(); const postMock = jest.fn(); const getMock = jest.fn(); +const reportInteractionMock = jest.fn(); jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), getBackendSrv: () => ({ fetch: fetchMock, post: postMock, get: getMock }), + reportInteraction: (...args: object[]) => { + reportInteractionMock(...args); + }, })); jest.mock('app/core/core', () => ({ @@ -84,6 +88,7 @@ describe('Explore: Query History', () => { fetchMock.mockClear(); postMock.mockClear(); getMock.mockClear(); + reportInteractionMock.mockClear(); tearDown(); }); @@ -109,6 +114,11 @@ describe('Explore: Query History', () => { // previously added query is in query history await openQueryHistory(); await assertQueryHistoryExists(RAW_QUERY); + + expect(reportInteractionMock).toBeCalledTimes(2); + expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', { + queryHistoryEnabled: false, + }); }); it('adds recently added query if the query history panel is already open', async () => { @@ -159,10 +169,17 @@ describe('Explore: Query History', () => { starQueryHistory(1, ExploreId.left); await assertQueryHistoryIsStarred([false, true], ExploreId.left); await assertQueryHistoryIsStarred([false, true], ExploreId.right); + expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_starred', { + queryHistoryEnabled: false, + newValue: true, + }); deleteQueryHistory(0, ExploreId.left); await assertQueryHistory(['{"expr":"query #1"}'], ExploreId.left); await assertQueryHistory(['{"expr":"query #1"}'], ExploreId.right); + expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_deleted', { + queryHistoryEnabled: false, + }); }); it('updates query history settings', async () => { @@ -198,6 +215,9 @@ describe('Explore: Query History', () => { await openQueryHistory(); expect(postMock).not.toBeCalledWith('/api/query-history/migrate', { queries: [] }); + expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', { + queryHistoryEnabled: false, + }); }); it('migrates query history from local storage', async () => { @@ -225,6 +245,9 @@ describe('Explore: Query History', () => { url: expect.stringMatching('/api/query-history/migrate'), }) ); + expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', { + queryHistoryEnabled: true, + }); }); });