From 98c56106ce1bad1a6ab09ad3635214f7f0109cb8 Mon Sep 17 00:00:00 2001 From: sareyu Date: Mon, 14 Oct 2024 15:07:29 +0300 Subject: [PATCH 1/3] feat(RunningQueries): add userSID search --- .../Diagnostics/TopQueries/RunningQueriesData.tsx | 13 +++++++++++-- .../Tenant/Diagnostics/TopQueries/TopQueries.tsx | 8 +++----- .../Diagnostics/TopQueries/TopQueriesData.tsx | 8 +++----- .../Tenant/Diagnostics/TopQueries/i18n/en.json | 2 +- .../reducers/executeTopQueries/executeTopQueries.ts | 5 ++++- src/store/reducers/executeTopQueries/utils.ts | 4 +++- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx b/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx index f5e85059a..b989444b8 100644 --- a/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx +++ b/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx @@ -4,6 +4,7 @@ import {ResponseError} from '../../../../components/Errors/ResponseError'; import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/ResizeableDataTable'; import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout'; import {topQueriesApi} from '../../../../store/reducers/executeTopQueries/executeTopQueries'; +import type {KeyValueRow} from '../../../../types/api/query'; import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks'; import {parseQueryErrorToString} from '../../../../utils/query'; import {QUERY_TABLE_SETTINGS} from '../../utils/constants'; @@ -16,9 +17,11 @@ import i18n from './i18n'; interface Props { database: string; + onRowClick: (query: string) => void; + rowClassName: string; } -export const RunningQueriesData = ({database}: Props) => { +export const RunningQueriesData = ({database, onRowClick, rowClassName}: Props) => { const [autoRefreshInterval] = useAutoRefreshInterval(); const filters = useTypedSelector((state) => state.executeTopQueries); const {currentData, isFetching, error} = topQueriesApi.useGetRunningQueriesQuery( @@ -31,16 +34,22 @@ export const RunningQueriesData = ({database}: Props) => { const data = currentData?.resultSets?.[0].result || []; + const handleRowClick = (row: KeyValueRow) => { + return onRowClick(row.QueryText as string); + }; + return ( {error ? : null} - + rowClassName} /> diff --git a/src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx b/src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx index 8cbdd635d..65e90ca34 100644 --- a/src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +++ b/src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx @@ -93,6 +93,8 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => { dispatch(setTopQueriesFilters(value)); }; + const DataComponent = isTopQueries ? TopQueriesData : RunningQueriesData; + return ( @@ -115,11 +117,7 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => { /> ) : null} - {isTopQueries ? ( - - ) : ( - - )} + ); }; diff --git a/src/containers/Tenant/Diagnostics/TopQueries/TopQueriesData.tsx b/src/containers/Tenant/Diagnostics/TopQueries/TopQueriesData.tsx index f815e64df..8efdb7456 100644 --- a/src/containers/Tenant/Diagnostics/TopQueries/TopQueriesData.tsx +++ b/src/containers/Tenant/Diagnostics/TopQueries/TopQueriesData.tsx @@ -5,7 +5,6 @@ import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/Re import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout'; import {topQueriesApi} from '../../../../store/reducers/executeTopQueries/executeTopQueries'; import type {KeyValueRow} from '../../../../types/api/query'; -import {cn} from '../../../../utils/cn'; import {isSortableTopQueriesProperty} from '../../../../utils/diagnostics'; import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks'; import {parseQueryErrorToString} from '../../../../utils/query'; @@ -14,14 +13,13 @@ import {QUERY_TABLE_SETTINGS} from '../../utils/constants'; import {TOP_QUERIES_COLUMNS, TOP_QUERIES_COLUMNS_WIDTH_LS_KEY} from './getTopQueriesColumns'; import i18n from './i18n'; -const b = cn('kv-top-queries'); - interface Props { database: string; onRowClick: (query: string) => void; + rowClassName: string; } -export const TopQueriesData = ({database, onRowClick}: Props) => { +export const TopQueriesData = ({database, onRowClick, rowClassName}: Props) => { const [autoRefreshInterval] = useAutoRefreshInterval(); const filters = useTypedSelector((state) => state.executeTopQueries); const {currentData, isFetching, error} = topQueriesApi.useGetTopQueriesQuery( @@ -54,7 +52,7 @@ export const TopQueriesData = ({database, onRowClick}: Props) => { data={data || []} settings={QUERY_TABLE_SETTINGS} onRowClick={handleRowClick} - rowClassName={() => b('row')} + rowClassName={() => rowClassName} /> diff --git a/src/containers/Tenant/Diagnostics/TopQueries/i18n/en.json b/src/containers/Tenant/Diagnostics/TopQueries/i18n/en.json index 43ef7d1c0..7ccee9bb8 100644 --- a/src/containers/Tenant/Diagnostics/TopQueries/i18n/en.json +++ b/src/containers/Tenant/Diagnostics/TopQueries/i18n/en.json @@ -1,6 +1,6 @@ { "no-data": "No data", - "filter.text.placeholder": "Search by query text...", + "filter.text.placeholder": "Search by query text or userSID...", "mode_top": "Top", "mode_running": "Running", "col_user": "User", diff --git a/src/store/reducers/executeTopQueries/executeTopQueries.ts b/src/store/reducers/executeTopQueries/executeTopQueries.ts index 72a0bcea2..ebaaa5064 100644 --- a/src/store/reducers/executeTopQueries/executeTopQueries.ts +++ b/src/store/reducers/executeTopQueries/executeTopQueries.ts @@ -94,7 +94,10 @@ export const topQueriesApi = api.injectEndpoints({ {signal}, ) => { try { - const filterConditions = filters?.text ? `Query ILIKE '%${filters.text}%'` : ''; + const filterConditions = filters?.text + ? `Query ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%'` + : ''; + const commonQueryPart = `SELECT UserSID, QueryStartAt, Query as QueryText, ApplicationName from \`.sys/query_sessions\` WHERE ${filterConditions || 'true'}`; const queryText = `${commonQueryPart} AND Query NOT LIKE '${commonQueryPart}%' ORDER BY SessionStartAt limit 100`; diff --git a/src/store/reducers/executeTopQueries/utils.ts b/src/store/reducers/executeTopQueries/utils.ts index 78e955e8f..f1a7a893c 100644 --- a/src/store/reducers/executeTopQueries/utils.ts +++ b/src/store/reducers/executeTopQueries/utils.ts @@ -37,7 +37,9 @@ export function getFiltersConditions(path: string, filters?: TopQueriesFilters) } if (filters?.text) { - conditions.push(`QueryText ILIKE '%${filters.text}%'`); + conditions.push( + `(QueryText ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%')`, + ); } return conditions.join(' AND '); From 8915093560652378622e0a9916bf515d259b954b Mon Sep 17 00:00:00 2001 From: sareyu Date: Wed, 16 Oct 2024 12:43:34 +0300 Subject: [PATCH 2/3] fix: fixes --- .../Diagnostics/TopQueries/RunningQueriesData.tsx | 4 ++-- .../Tenant/Diagnostics/TopQueries/TopQueriesData.tsx | 4 ++-- .../reducers/executeTopQueries/executeTopQueries.ts | 11 ++++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx b/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx index b989444b8..a55ffeb1a 100644 --- a/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx +++ b/src/containers/Tenant/Diagnostics/TopQueries/RunningQueriesData.tsx @@ -24,7 +24,7 @@ interface Props { export const RunningQueriesData = ({database, onRowClick, rowClassName}: Props) => { const [autoRefreshInterval] = useAutoRefreshInterval(); const filters = useTypedSelector((state) => state.executeTopQueries); - const {currentData, isFetching, error} = topQueriesApi.useGetRunningQueriesQuery( + const {currentData, isLoading, error} = topQueriesApi.useGetRunningQueriesQuery( { database, filters, @@ -41,7 +41,7 @@ export const RunningQueriesData = ({database, onRowClick, rowClassName}: Props) return ( {error ? : null} - + { const [autoRefreshInterval] = useAutoRefreshInterval(); const filters = useTypedSelector((state) => state.executeTopQueries); - const {currentData, isFetching, error} = topQueriesApi.useGetTopQueriesQuery( + const {currentData, isLoading, error} = topQueriesApi.useGetTopQueriesQuery( { database, filters, @@ -44,7 +44,7 @@ export const TopQueriesData = ({database, onRowClick, rowClassName}: Props) => { return ( {error ? : null} - + item.QueryText !== queryText, + ); + } + return {data}; } catch (error) { return {error}; From 00166e7fd6343796944ae68e5c75176e6424d17c Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Wed, 16 Oct 2024 13:37:21 +0300 Subject: [PATCH 3/3] fix: tests --- tests/suites/tenant/diagnostics/Diagnostics.ts | 16 ++++++++-------- .../tenant/diagnostics/diagnostics.test.ts | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/suites/tenant/diagnostics/Diagnostics.ts b/tests/suites/tenant/diagnostics/Diagnostics.ts index bc41b1709..5737cac17 100644 --- a/tests/suites/tenant/diagnostics/Diagnostics.ts +++ b/tests/suites/tenant/diagnostics/Diagnostics.ts @@ -88,15 +88,15 @@ export class Table { } async waitForCellValueByHeader(row: number, header: string, value: string) { - const headers = await this.getHeaders(); - const colIndex = headers.indexOf(header); - if (colIndex === -1) { - throw new Error(`Header "${header}" not found`); - } - const cell = this.table.locator( - `tr.data-table__row:nth-child(${row}) td:nth-child(${colIndex + 1})`, - ); await retryAction(async () => { + const headers = await this.getHeaders(); + const colIndex = headers.indexOf(header); + if (colIndex === -1) { + throw new Error(`Header "${header}" not found`); + } + const cell = this.table.locator( + `tr.data-table__row:nth-child(${row}) td:nth-child(${colIndex + 1})`, + ); const cellValue = (await cell.innerText()).trim(); if (cellValue === value) { return true; diff --git a/tests/suites/tenant/diagnostics/diagnostics.test.ts b/tests/suites/tenant/diagnostics/diagnostics.test.ts index 908415d54..315374175 100644 --- a/tests/suites/tenant/diagnostics/diagnostics.test.ts +++ b/tests/suites/tenant/diagnostics/diagnostics.test.ts @@ -65,7 +65,6 @@ test.describe('Diagnostics tab', async () => { const diagnostics = new Diagnostics(page); await diagnostics.clickTab(DiagnosticsTab.Queries); await diagnostics.clickRadioSwitch(QueriesSwitch.Running); - expect(await diagnostics.table.getRowCount()).toBe(1); expect( await diagnostics.table.waitForCellValueByHeader(1, 'QueryText', longRunningQuery), ).toBe(true);