Skip to content

Commit 3911a5e

Browse files
Merge pull request #37 from RedisInsight/feature/RI-2075_Telemetry_Workbench
#RI-2075 Telemetry for Workbench page
2 parents a35b113 + 33282bd commit 3911a5e

File tree

14 files changed

+188
-114
lines changed

14 files changed

+188
-114
lines changed

redisinsight/ui/src/components/query-card/QueryCard.tsx

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import React, { useEffect, useState } from 'react'
22
import { useSelector } from 'react-redux'
33
import cx from 'classnames'
44
import { EuiLoadingContent, keys } from '@elastic/eui'
5+
import { useParams } from 'react-router-dom'
6+
57
import { WBQueryType } from 'uiSrc/pages/workbench/constants'
68
import { getWBQueryType, Nullable, getVisualizationsByCommand, Maybe } from 'uiSrc/utils'
7-
89
import { appPluginsSelector } from 'uiSrc/slices/app/plugins'
910
import { IPluginVisualization } from 'uiSrc/slices/interfaces'
1011
import { CommandExecutionStatus } from 'uiSrc/slices/interfaces/cli'
12+
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
13+
import { appRedisCommandsSelector } from 'uiSrc/slices/app/redis-commands'
1114

1215
import QueryCardHeader from './QueryCardHeader'
1316
import QueryCardCliResult from './QueryCardCliResult'
@@ -34,10 +37,9 @@ const getDefaultPlugin = (views: IPluginVisualization[], query: string) =>
3437
getVisualizationsByCommand(query, views).find((view) => view.default)?.uniqId || ''
3538

3639
const QueryCard = (props: Props) => {
37-
const { visualizations = [] } = useSelector(appPluginsSelector)
3840
const {
3941
id,
40-
query,
42+
query = '',
4143
data,
4244
status,
4345
fromStore,
@@ -48,15 +50,19 @@ const QueryCard = (props: Props) => {
4850
loading
4951
} = props
5052

53+
const { visualizations = [] } = useSelector(appPluginsSelector)
54+
const { commandsArray: REDIS_COMMANDS_ARRAY } = useSelector(appRedisCommandsSelector)
55+
56+
const { instanceId = '' } = useParams<{ instanceId: string }>()
5157
const [isOpen, setIsOpen] = useState(!fromStore)
5258
const [isFullScreen, setIsFullScreen] = useState<boolean>(false)
5359
const [result, setResult] = useState<Nullable<any>>(data)
5460
const [queryType, setQueryType] = useState<WBQueryType>(getWBQueryType(query, visualizations))
5561
const [viewTypeSelected, setViewTypeSelected] = useState<WBQueryType>(queryType)
62+
const [summaryText, setSummaryText] = useState<string>('')
5663
const [selectedViewValue, setSelectedViewValue] = useState<string>(
5764
getDefaultPlugin(visualizations, query) || queryType
5865
)
59-
const [summaryText, setSummaryText] = useState<string>('')
6066

6167
useEffect(() => {
6268
window.addEventListener('keydown', handleEscFullScreen)
@@ -72,7 +78,17 @@ const QueryCard = (props: Props) => {
7278
}
7379

7480
const toggleFullScreen = () => {
75-
setIsFullScreen((value) => !value)
81+
setIsFullScreen((isFull) => {
82+
sendEventTelemetry({
83+
event: TelemetryEvent.WORKBENCH_RESULTS_IN_FULL_SCREEN,
84+
eventData: {
85+
databaseId: instanceId,
86+
state: isFull ? 'Close' : 'Open'
87+
}
88+
})
89+
90+
return !isFull
91+
})
7692
}
7793

7894
useEffect(() => {
@@ -94,8 +110,25 @@ const QueryCard = (props: Props) => {
94110
}
95111
}, [data, time])
96112

113+
const sendEventToggleOpenTelemetry = () => {
114+
const matchedCommand = REDIS_COMMANDS_ARRAY.find((commandName) =>
115+
query.toUpperCase().startsWith(commandName))
116+
117+
sendEventTelemetry({
118+
event: isOpen
119+
? TelemetryEvent.WORKBENCH_RESULTS_COLLAPSED
120+
: TelemetryEvent.WORKBENCH_RESULTS_EXPANDED,
121+
eventData: {
122+
databaseId: instanceId,
123+
command: matchedCommand ?? query.split(' ')?.[0]
124+
}
125+
})
126+
}
127+
97128
const toggleOpen = () => {
98129
if (isFullScreen) return
130+
131+
sendEventToggleOpenTelemetry()
99132
setIsOpen(!isOpen)
100133

101134
if (!isOpen && !data) {

redisinsight/ui/src/components/query-card/QueryCardHeader/QueryCardHeader.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import {
1212
EuiToolTip,
1313
} from '@elastic/eui'
1414
import { format } from 'date-fns'
15+
import { useParams } from 'react-router-dom'
1516

1617
import { Theme } from 'uiSrc/constants'
1718
import { getVisualizationsByCommand, truncateText, urlForAsset } from 'uiSrc/utils'
1819
import { ThemeContext } from 'uiSrc/contexts/themeContext'
1920
import { appPluginsSelector } from 'uiSrc/slices/app/plugins'
21+
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
2022
import { getViewTypeOptions, WBQueryType } from 'uiSrc/pages/workbench/constants'
2123

2224
import DefaultPluginIconDark from 'uiSrc/assets/img/workbench/default_view_dark.svg'
@@ -57,6 +59,7 @@ const QueryCardHeader = (props: Props) => {
5759
} = props
5860

5961
const { visualizations = [] } = useSelector(appPluginsSelector)
62+
const { instanceId = '' } = useParams<{ instanceId: string }>()
6063

6164
const { theme } = useContext(ThemeContext)
6265

@@ -66,6 +69,12 @@ const QueryCardHeader = (props: Props) => {
6669
}
6770

6871
const handleCopy = (event: React.MouseEvent, text: string) => {
72+
sendEventTelemetry({
73+
event: TelemetryEvent.WORKBENCH_COMMAND_COPIED,
74+
eventData: {
75+
databaseId: instanceId
76+
}
77+
})
6978
eventStop(event)
7079
navigator.clipboard.writeText(text)
7180
}
@@ -81,11 +90,23 @@ const QueryCardHeader = (props: Props) => {
8190
}
8291

8392
const handleQueryDelete = (event: React.MouseEvent) => {
93+
sendEventTelemetry({
94+
event: TelemetryEvent.WORKBENCH_COMMAND_DELETE_COMMAND,
95+
eventData: {
96+
databaseId: instanceId
97+
}
98+
})
8499
eventStop(event)
85100
onQueryDelete()
86101
}
87102

88103
const handleQueryReRun = (event: React.MouseEvent) => {
104+
sendEventTelemetry({
105+
event: TelemetryEvent.WORKBENCH_COMMAND_RUN_AGAIN,
106+
eventData: {
107+
databaseId: instanceId
108+
}
109+
})
89110
eventStop(event)
90111
onQueryReRun()
91112
}

redisinsight/ui/src/components/query/Query/Query.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
import React, { useContext, useEffect } from 'react'
22
import { useSelector } from 'react-redux'
33
import { findIndex } from 'lodash'
4+
import { decode } from 'html-entities'
45
import cx from 'classnames'
56
import { EuiButtonIcon, EuiText, EuiToolTip } from '@elastic/eui'
67
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'
78
import MonacoEditor from 'react-monaco-editor'
9+
import { useParams } from 'react-router-dom'
810

911
import {
1012
Theme,
1113
MonacoLanguage,
1214
redisLanguageConfig,
1315
KEYBOARD_SHORTCUTS,
1416
} from 'uiSrc/constants'
17+
import {
18+
getMultiCommands,
19+
getRedisCompletionProvider,
20+
getRedisMonarchTokensProvider,
21+
removeMonacoComments,
22+
splitMonacoValuePerLines
23+
} from 'uiSrc/utils'
1524
import { ThemeContext } from 'uiSrc/contexts/themeContext'
16-
import { getRedisCompletionProvider, getRedisMonarchTokensProvider } from 'uiSrc/utils'
1725
import { WBQueryType } from 'uiSrc/pages/workbench/constants'
1826
import { KeyboardShortcut } from 'uiSrc/components'
1927
import { appRedisCommandsSelector } from 'uiSrc/slices/app/redis-commands'
28+
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
2029

2130
import styles from './styles.module.scss'
2231

@@ -31,6 +40,8 @@ export interface Props {
3140

3241
const Query = (props: Props) => {
3342
const { query = '', setQuery, onKeyDown, onSubmit, setQueryEl } = props
43+
const { instanceId = '' } = useParams<{ instanceId: string }>()
44+
3445
const {
3546
commandsArray: REDIS_COMMANDS_ARRAY,
3647
spec: REDIS_COMMANDS_SPEC
@@ -54,7 +65,35 @@ const Query = (props: Props) => {
5465
onKeyDown?.(e, query)
5566
}
5667

68+
const sendEventSubmitTelemetry = (commandInit = query) => {
69+
const eventData = (() => {
70+
const commands = splitMonacoValuePerLines(commandInit)
71+
72+
const [commandLine, ...rest] = commands.map((command = '') => {
73+
const matchedCommand = REDIS_COMMANDS_ARRAY.find((commandName) =>
74+
command.toUpperCase().startsWith(commandName))
75+
return matchedCommand ?? command.split(' ')?.[0]
76+
})
77+
const multiCommands = getMultiCommands(rest)
78+
79+
const command = removeMonacoComments(decode([commandLine, multiCommands].join('\n')).trim())
80+
81+
return {
82+
command,
83+
databaseId: instanceId,
84+
multiple: multiCommands ? 'Multiple' : 'Single'
85+
}
86+
})()
87+
88+
sendEventTelemetry({
89+
event: TelemetryEvent.WORKBENCH_COMMAND_SUBMITTED,
90+
eventData
91+
})
92+
}
93+
5794
const handleSubmit = (value?: string) => {
95+
sendEventSubmitTelemetry(value)
96+
5897
onSubmit(value)
5998
}
6099

redisinsight/ui/src/constants/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export * from './keys'
88
export * from './table'
99
export * from './redisinsight'
1010
export * from './commands'
11-
export * from './workbenchPreselects'
1211
export * from './monaco'
1312
export * from './monacoRedis'
1413
export * from './keyboardShortcuts'

redisinsight/ui/src/constants/workbenchPreselects.ts

Lines changed: 0 additions & 90 deletions
This file was deleted.

redisinsight/ui/src/pages/workbench/WorkbenchPage.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
1-
import React, { useEffect } from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
3+
import { useParams } from 'react-router-dom'
4+
35
import { formatLongName, getDbIndex, setTitle } from 'uiSrc/utils'
46
import { PageNames } from 'uiSrc/constants'
57
import { connectedInstanceSelector } from 'uiSrc/slices/instances'
68
import { setLastPageContext } from 'uiSrc/slices/app/context'
79
import { loadPluginsAction } from 'uiSrc/slices/app/plugins'
10+
import { sendPageViewTelemetry, TelemetryPageView } from 'uiSrc/telemetry'
11+
import { appAnalyticsInfoSelector } from 'uiSrc/slices/app/info'
812
import WBViewWrapper from './components/wb-view'
913

1014
const WorkbenchPage = () => {
11-
const { name, db } = useSelector(connectedInstanceSelector)
15+
const [isPageViewSent, setIsPageViewSent] = useState(false)
16+
17+
const { name: connectedInstanceName, db } = useSelector(connectedInstanceSelector)
18+
const { identified: analyticsIdentified } = useSelector(appAnalyticsInfoSelector)
19+
20+
const { instanceId } = useParams<{ instanceId: string }>()
1221

1322
const dispatch = useDispatch()
14-
setTitle(`${formatLongName(name, 33, 0, '...')} ${getDbIndex(db)} - Workbench`)
23+
setTitle(`${formatLongName(connectedInstanceName, 33, 0, '...')} ${getDbIndex(db)} - Workbench`)
24+
25+
useEffect(() => {
26+
if (connectedInstanceName && !isPageViewSent && analyticsIdentified) {
27+
sendPageView(instanceId)
28+
}
29+
}, [connectedInstanceName, isPageViewSent, analyticsIdentified])
30+
31+
const sendPageView = (instanceId: string) => {
32+
sendPageViewTelemetry({
33+
name: TelemetryPageView.WORKBENCH_PAGE,
34+
databaseId: instanceId
35+
})
36+
setIsPageViewSent(true)
37+
}
1538

1639
useEffect(() => {
1740
dispatch(loadPluginsAction())

0 commit comments

Comments
 (0)