Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
"@types/redux-mock-store": "^1.0.2",
"@types/segment-analytics": "^0.0.34",
"@types/supertest": "^2.0.8",
"@types/uuid": "^8.3.4",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1",
Expand Down Expand Up @@ -265,7 +266,8 @@
"socket.io-client": "^4.4.0",
"unified": "^10.1.1",
"unist-util-visit": "^4.1.0",
"url-parse": "^1.5.10"
"url-parse": "^1.5.10",
"uuid": "^8.3.2"
},
"devEngines": {
"node": ">=14.x <16",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { cloneDeep } from 'lodash'
import React from 'react'
import MockedSocket from 'socket.io-mock'
import socketIO from 'socket.io-client'
import { monitorSelector, setMonitorLoadingPause, setSocket, stopMonitor } from 'uiSrc/slices/cli/monitor'
import {
monitorSelector,
setMonitorLoadingPause,
pauseMonitor,
setSocket,
stopMonitor,
lockResume
} from 'uiSrc/slices/cli/monitor'
import { cleanup, mockedStore, render } from 'uiSrc/utils/test-utils'
import { MonitorEvent, SocketEvent } from 'uiSrc/constants'
import MonitorConfig from './MonitorConfig'
Expand Down Expand Up @@ -100,7 +107,7 @@ describe('MonitorConfig', () => {
const afterRenderActions = [
setSocket(socket),
setMonitorLoadingPause(true),
stopMonitor()
pauseMonitor()
]
expect(store.getActions()).toEqual([...afterRenderActions])

Expand All @@ -123,8 +130,7 @@ describe('MonitorConfig', () => {

const afterRenderActions = [
setSocket(socket),
setMonitorLoadingPause(true),
stopMonitor()
setMonitorLoadingPause(true)
]
expect(store.getActions()).toEqual([...afterRenderActions])

Expand All @@ -144,7 +150,9 @@ describe('MonitorConfig', () => {
const afterRenderActions = [
setSocket(socket),
setMonitorLoadingPause(true),
stopMonitor()
pauseMonitor(),
stopMonitor(),
lockResume()
]
expect(store.getActions()).toEqual([...afterRenderActions])

Expand Down
21 changes: 14 additions & 7 deletions redisinsight/ui/src/components/monitor-config/MonitorConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { debounce } from 'lodash'
import { io } from 'socket.io-client'
import { v4 as uuidv4 } from 'uuid'

import {
setSocket,
Expand All @@ -11,7 +12,9 @@ import {
setError,
resetMonitorItems,
setStartTimestamp,
setMonitorLoadingPause
setMonitorLoadingPause,
setLogFileId,
pauseMonitor, lockResume
} from 'uiSrc/slices/cli/monitor'
import { getBaseApiUrl } from 'uiSrc/utils'
import { MonitorErrorMessages, MonitorEvent, SocketErrors, SocketEvent } from 'uiSrc/constants'
Expand All @@ -24,7 +27,7 @@ import ApiStatusCode from '../../constants/apiStatusCode'
interface IProps {
retryDelay?: number;
}
const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {
const MonitorConfig = ({ retryDelay = 15000 } : IProps) => {
const { id: instanceId = '' } = useSelector(connectedInstanceSelector)
const { socket, isRunning, isPaused, isSaveToFile, isMinimizedMonitor, isShowMonitor } = useSelector(monitorSelector)

Expand All @@ -48,6 +51,8 @@ const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {
if (!isRunning || !instanceId || socket?.connected) {
return
}
const logFileId = `_redis_${uuidv4()}`
const timestamp = Date.now()
let retryTimer: NodeJS.Timer

// Create SocketIO connection to instance by instanceId
Expand Down Expand Up @@ -75,17 +80,20 @@ const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {

const handleDisconnect = () => {
newSocket.removeAllListeners()
dispatch(pauseMonitor())
dispatch(stopMonitor())
dispatch(lockResume())
}

newSocket.on(SocketEvent.Connect, () => {
// Trigger Monitor event
clearTimeout(retryTimer)
const timestampStart = Date.now()
dispatch(setStartTimestamp(timestampStart))

dispatch(setLogFileId(logFileId))
dispatch(setStartTimestamp(timestamp))
newSocket.emit(
MonitorEvent.Monitor,
{ logFileId: isSaveToFile ? timestampStart.toString() : null },
{ logFileId: isSaveToFile ? logFileId : null },
handleMonitorEvents
)
})
Expand All @@ -101,7 +109,7 @@ const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {

payloads.push({ isError: true, time: `${Date.now()}`, ...payload })
setNewItems(payloads, () => { payloads.length = 0 })
dispatch(stopMonitor())
dispatch(pauseMonitor())
})

// Catch disconnect
Expand All @@ -117,7 +125,6 @@ const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {
newSocket.on(SocketEvent.ConnectionError, (error) => {
payloads.push({ isError: true, time: `${Date.now()}`, message: getErrorMessage(error) })
setNewItems(payloads, () => { payloads.length = 0 })
dispatch(stopMonitor())
})
}, [instanceId, isRunning, isSaveToFile])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const Monitor = (props: Props) => {
)}
</div>
)}
{isStarted && isPaused && !isSaveToFile && (
{isRunning && isPaused && !isSaveToFile && (
<div data-testid="monitor-stopped" className={styles.monitorStoppedText}>
Profiler is paused.
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,17 @@ export interface Props {

const MonitorHeader = ({ handleRunMonitor }: Props) => {
const { instanceId = '' } = useParams<{ instanceId: string }>()
const { isRunning, isPaused, isStarted, items = [], error, loadingPause } = useSelector(monitorSelector)
const {
isRunning,
isPaused,
isResumeLocked,
isStarted,
items = [],
error,
loadingPause
} = useSelector(monitorSelector)
const isErrorShown = !!error && !isRunning
const disabledPause = isErrorShown || isResumeLocked || loadingPause
const dispatch = useDispatch()

const handleCloseMonitor = () => {
Expand Down Expand Up @@ -81,19 +90,19 @@ const MonitorHeader = ({ handleRunMonitor }: Props) => {
{isStarted && (
<EuiFlexItem grow={false} className={styles.actions}>
<EuiToolTip
content={isErrorShown ? '' : (!isPaused ? 'Pause' : 'Resume')}
content={(isErrorShown || isResumeLocked) ? '' : (!isPaused ? 'Pause' : 'Resume')}
anchorClassName="inline-flex"
>
<EuiButtonIcon
iconType={isErrorShown ? BanIcon : (!isPaused ? 'pause' : 'play')}
iconType={(isErrorShown || isResumeLocked) ? BanIcon : (!isPaused ? 'pause' : 'play')}
onClick={() => handleRunMonitor()}
aria-label="start/stop monitor"
data-testid="toggle-run-monitor"
disabled={isErrorShown || loadingPause}
disabled={disabledPause}
/>
</EuiToolTip>
<EuiToolTip
content={!isStarted || !items.length ? '' : 'Clear Profiler window'}
content={!isStarted || !items.length ? '' : 'Clear Profiler Window'}
anchorClassName={cx('inline-flex', { transparent: !isStarted || !items.length })}
>
<EuiButtonIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import { cutDurationText, getBaseApiUrl } from 'uiSrc/utils'

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

const MIDDLE_SCREEN_RESOLUTION = 460
const SMALL_SCREEN_RESOLUTION = 360
const PADDINGS_OUTSIDE = 12
const MIDDLE_SCREEN_RESOLUTION = 460 - PADDINGS_OUTSIDE
const SMALL_SCREEN_RESOLUTION = 360 - PADDINGS_OUTSIDE

const MonitorLog = () => {
const { timestamp } = useSelector(monitorSelector)
const { timestamp, logFileId } = useSelector(monitorSelector)
const dispatch = useDispatch()

const duration = cutDurationText(
Expand All @@ -26,7 +27,7 @@ const MonitorLog = () => {
)
)
const baseApiUrl = getBaseApiUrl()
const linkToDownload = `${baseApiUrl}/api/${ApiEndpoints.PROFILER_LOGS}/${timestamp.start}`
const linkToDownload = `${baseApiUrl}/api/${ApiEndpoints.PROFILER_LOGS}/${logFileId}`
const isElectron = process.env.APP_ENV === AppEnv.ELECTRON

const downloadBtnProps: any = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const MonitorWrapper = () => {
dispatch(togglePauseMonitor())
}

const onRunMonitor = (isSaveToLog?: boolean) => {
const onRunMonitor = (isSaveToLog: boolean = false) => {
sendEventTelemetry({
event: TelemetryEvent.PROFILER_STARTED,
eventData: {
Expand Down
25 changes: 20 additions & 5 deletions redisinsight/ui/src/slices/cli/monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ export const initialState: StateMonitor = {
isRunning: false,
isStarted: false,
isPaused: false,
isResumeLocked: false,
isSaveToFile: false,
isMinimizedMonitor: false,
socket: null,
error: '',
items: [],
logFile: null,
logFileId: null,
timestamp: {
start: 0,
paused: 0,
Expand Down Expand Up @@ -65,6 +66,10 @@ const monitorSlice = createSlice({
state.isSaveToFile = payload
},

setLogFileId: (state, { payload }) => {
state.logFileId = payload
},

setStartTimestamp: (state, { payload }) => {
state.timestamp.start = payload
state.timestamp.unPaused = state.timestamp.start
Expand All @@ -81,16 +86,18 @@ const monitorSlice = createSlice({
}
},

pauseMonitor: (state) => {
state.isPaused = true
state.timestamp.paused = Date.now()
state.timestamp.duration += state.timestamp.paused - state.timestamp.unPaused
},

setMonitorLoadingPause: (state, { payload }) => {
state.loadingPause = payload
},

stopMonitor: (state) => {
state.isRunning = false
state.error = ''
state.timestamp.paused = Date.now()
state.timestamp.duration += state.timestamp.paused - state.timestamp.unPaused
state.isPaused = false
},

resetProfiler: (state) => {
Expand Down Expand Up @@ -126,6 +133,11 @@ const monitorSlice = createSlice({
setError: (state, { payload }) => {
state.error = payload
},

lockResume: (state) => {
state.isResumeLocked = true
state.isPaused = true
}
},
})

Expand All @@ -137,8 +149,11 @@ export const {
toggleHideMonitor,
setSocket,
togglePauseMonitor,
pauseMonitor,
lockResume,
startMonitor,
setStartTimestamp,
setLogFileId,
setMonitorLoadingPause,
stopMonitor,
resetProfiler,
Expand Down
3 changes: 2 additions & 1 deletion redisinsight/ui/src/slices/interfaces/monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ export interface StateMonitor {
isRunning: boolean
isStarted: boolean
isPaused: boolean
isResumeLocked: boolean
isSaveToFile: boolean
socket: Nullable<Socket>
items: IMonitorDataPayload[]
error: string
logFile: any
logFileId: Nullable<string>
timestamp: {
start: number
paused: number
Expand Down
7 changes: 1 addition & 6 deletions redisinsight/ui/src/slices/tests/cli/monitor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,7 @@ describe('monitor slice', () => {
// Arrange
const state: typeof initialState = {
...initialState,
isRunning: false,
timestamp: {
...initialState.timestamp,
paused: Date.now(),
duration: Date.now() - initialState.timestamp.unPaused
}
isRunning: false
}

// Act
Expand Down
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2531,6 +2531,11 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==

"@types/uuid@^8.3.4":
version "8.3.4"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==

"@types/verror@^1.10.3":
version "1.10.5"
resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.5.tgz#2a1413aded46e67a1fe2386800e291123ed75eb1"
Expand Down Expand Up @@ -15323,7 +15328,7 @@ uuid@^3.3.2, uuid@^3.4.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==

uuid@^8.3.0:
uuid@^8.3.0, uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
Expand Down