diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx index 4c9e9db80..3419c76e8 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx @@ -68,7 +68,7 @@ export function TenantStorage({tenantName, metrics}: TenantStorageProps) { - + ); diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx index 52fe25942..8f4ed26f9 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx @@ -16,18 +16,18 @@ import i18n from '../i18n'; import '../TenantOverview.scss'; interface TopTablesProps { - path: string; + database: string; } const TOP_TABLES_COLUMNS_WIDTH_LS_KEY = 'topTablesTableColumnsWidth'; -export function TopTables({path}: TopTablesProps) { +export function TopTables({database}: TopTablesProps) { const location = useLocation(); const [autoRefreshInterval] = useAutoRefreshInterval(); const {currentData, error, isFetching} = topTablesApi.useGetTopTablesQuery( - {path}, + {database}, {pollingInterval: autoRefreshInterval}, ); const loading = isFetching && currentData === undefined; diff --git a/src/store/reducers/cluster/cluster.ts b/src/store/reducers/cluster/cluster.ts index 2768766f9..753d5d7dc 100644 --- a/src/store/reducers/cluster/cluster.ts +++ b/src/store/reducers/cluster/cluster.ts @@ -87,7 +87,7 @@ export const clusterApi = api.injectEndpoints({ } try { - const query = createSelectClusterGroupsQuery(clusterRoot); + const query = createSelectClusterGroupsQuery(); // Normally query request should be fulfilled within 300-400ms even on very big clusters // Table with stats is supposed to be very small (less than 10 rows) diff --git a/src/store/reducers/cluster/utils.ts b/src/store/reducers/cluster/utils.ts index 1664a3cf1..2f69ddad2 100644 --- a/src/store/reducers/cluster/utils.ts +++ b/src/store/reducers/cluster/utils.ts @@ -1,11 +1,12 @@ import type {TClusterInfoV2, TStorageStats} from '../../../types/api/cluster'; import type {ExecuteQueryResponse, KeyValueRow} from '../../../types/api/query'; +import {QUERY_TECHNICAL_MARK} from '../../../utils/constants'; import {parseQueryAPIResponse} from '../../../utils/query'; import type {ClusterGroupsStats} from './types'; -export const createSelectClusterGroupsQuery = (clusterRoot: string) => { - return ` +export const createSelectClusterGroupsQuery = () => { + return `${QUERY_TECHNICAL_MARK} SELECT PDiskFilter, ErasureSpecies, @@ -13,8 +14,8 @@ SELECT CurrentAllocatedSize, CurrentGroupsCreated, AvailableGroupsToCreate - FROM \`${clusterRoot}/.sys/ds_storage_stats\` - ORDER BY CurrentGroupsCreated DESC; +FROM \`.sys/ds_storage_stats\` +ORDER BY CurrentGroupsCreated DESC; `; }; diff --git a/src/store/reducers/executeTopQueries/executeTopQueries.ts b/src/store/reducers/executeTopQueries/executeTopQueries.ts index 7e99fae7a..b7a5a8520 100644 --- a/src/store/reducers/executeTopQueries/executeTopQueries.ts +++ b/src/store/reducers/executeTopQueries/executeTopQueries.ts @@ -3,6 +3,7 @@ import type {SortOrder} from '@gravity-ui/react-data-table'; import {createSlice} from '@reduxjs/toolkit'; import type {PayloadAction} from '@reduxjs/toolkit'; +import {QUERY_TECHNICAL_MARK} from '../../../utils/constants'; import {prepareOrderByFromTableSort} from '../../../utils/hooks/useTableSort'; import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../utils/query'; import {api} from '../api'; @@ -12,8 +13,6 @@ import {getFiltersConditions} from './utils'; const initialState: TopQueriesFilters = {}; -const QUERY_TECHNICAL_MARK = '/*UI-QUERY-EXCLUDE*/'; - const slice = createSlice({ name: 'executeTopQueries', initialState, @@ -27,13 +26,13 @@ const slice = createSlice({ export const {setTopQueriesFilters} = slice.actions; export default slice.reducer; -const getQueryText = (path: string, filters?: TopQueriesFilters, sortOrder?: SortOrder[]) => { - const filterConditions = getFiltersConditions(path, filters); +const getQueryText = (filters?: TopQueriesFilters, sortOrder?: SortOrder[]) => { + const filterConditions = getFiltersConditions(filters); const orderBy = prepareOrderByFromTableSort(sortOrder); - return ` -SELECT ${QUERY_TECHNICAL_MARK} + return `${QUERY_TECHNICAL_MARK} +SELECT CPUTime as CPUTimeUs, QueryText, IntervalEnd, @@ -42,13 +41,32 @@ SELECT ${QUERY_TECHNICAL_MARK} ReadBytes, UserSID, Duration -FROM \`${path}/.sys/top_queries_by_cpu_time_one_hour\` +FROM \`.sys/top_queries_by_cpu_time_one_hour\` WHERE ${filterConditions || 'true'} AND QueryText NOT LIKE '%${QUERY_TECHNICAL_MARK}%' ${orderBy} LIMIT 100 `; }; +function getRunningQueriesText(filters?: TopQueriesFilters, sortOrder?: SortOrder[]) { + const filterConditions = filters?.text + ? `Query ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%'` + : ''; + + const orderBy = prepareOrderByFromTableSort(sortOrder); + + return `${QUERY_TECHNICAL_MARK} +SELECT + UserSID, + QueryStartAt, + Query as QueryText, + ApplicationName +FROM \`.sys/query_sessions\` +WHERE ${filterConditions || 'true'} AND Query NOT LIKE '%${QUERY_TECHNICAL_MARK}%' +${orderBy} +LIMIT 100`; +} + interface TopQueriesRequestParams { database: string; filters?: TopQueriesFilters; @@ -68,7 +86,7 @@ export const topQueriesApi = api.injectEndpoints({ try { const response = await window.api.viewer.sendQuery( { - query: getQueryText(database, preparedFilters, sortOrder), + query: getQueryText(preparedFilters, sortOrder), database, action: 'execute-scan', }, @@ -102,24 +120,9 @@ export const topQueriesApi = api.injectEndpoints({ getRunningQueries: build.query({ queryFn: async ({database, filters, sortOrder}: TopQueriesRequestParams, {signal}) => { try { - const filterConditions = filters?.text - ? `Query ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%'` - : ''; - - const orderBy = prepareOrderByFromTableSort(sortOrder); - - const queryText = `SELECT ${QUERY_TECHNICAL_MARK} - UserSID, QueryStartAt, Query as QueryText, ApplicationName - FROM - \`.sys/query_sessions\` - WHERE - ${filterConditions || 'true'} AND Query NOT LIKE '%${QUERY_TECHNICAL_MARK}%' - ${orderBy} - LIMIT 100`; - const response = await window.api.viewer.sendQuery( { - query: queryText, + query: getRunningQueriesText(filters, sortOrder), database, action: 'execute-scan', }, diff --git a/src/store/reducers/executeTopQueries/utils.ts b/src/store/reducers/executeTopQueries/utils.ts index f1a7a893c..03242cf0a 100644 --- a/src/store/reducers/executeTopQueries/utils.ts +++ b/src/store/reducers/executeTopQueries/utils.ts @@ -5,13 +5,13 @@ import type {TopQueriesFilters} from './types'; const endTimeColumn = 'EndTime'; const intervalEndColumn = 'IntervalEnd'; -const getMaxIntervalSubquery = (path: string) => `( +const getMaxIntervalSubquery = () => `( SELECT MAX(${intervalEndColumn}) - FROM \`${path}/.sys/top_queries_by_cpu_time_one_hour\` + FROM \`.sys/top_queries_by_cpu_time_one_hour\` )`; -export function getFiltersConditions(path: string, filters?: TopQueriesFilters) { +export function getFiltersConditions(filters?: TopQueriesFilters) { const conditions: string[] = []; const to = dateTimeParse(Number(filters?.to) || filters?.to)?.valueOf(); const from = dateTimeParse(Number(filters?.from) || filters?.from)?.valueOf(); @@ -33,7 +33,7 @@ export function getFiltersConditions(path: string, filters?: TopQueriesFilters) // If there is no filters, return queries, that were executed in the last hour if (!from && !to) { - conditions.push(`${intervalEndColumn} IN ${getMaxIntervalSubquery(path)}`); + conditions.push(`${intervalEndColumn} IN ${getMaxIntervalSubquery()}`); } if (filters?.text) { diff --git a/src/store/reducers/shardsWorkload/shardsWorkload.ts b/src/store/reducers/shardsWorkload/shardsWorkload.ts index a2da79903..0f6230037 100644 --- a/src/store/reducers/shardsWorkload/shardsWorkload.ts +++ b/src/store/reducers/shardsWorkload/shardsWorkload.ts @@ -3,6 +3,7 @@ import type {SortOrder} from '@gravity-ui/react-data-table'; import {createSlice} from '@reduxjs/toolkit'; import type {PayloadAction} from '@reduxjs/toolkit'; +import {QUERY_TECHNICAL_MARK} from '../../../utils/constants'; import {prepareOrderByFromTableSort} from '../../../utils/hooks/useTableSort'; import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../utils/query'; import {api} from '../api'; @@ -37,13 +38,11 @@ function getFiltersConditions(filters?: ShardsWorkloadFilters) { function createShardQueryHistorical( path: string, + database: string, filters?: ShardsWorkloadFilters, sortOrder?: SortOrder[], - tenantName?: string, ) { - const pathSelect = tenantName - ? `CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path` - : 'Path'; + const pathSelect = `CAST(SUBSTRING(CAST(Path AS String), ${database.length}) AS Utf8) AS Path`; let where = `Path='${path}' OR Path LIKE '${path}/%'`; @@ -54,7 +53,8 @@ function createShardQueryHistorical( const orderBy = prepareOrderByFromTableSort(sortOrder); - return `SELECT + return `${QUERY_TECHNICAL_MARK} +SELECT ${pathSelect}, TabletId, CPUCores, @@ -69,14 +69,13 @@ ${orderBy} LIMIT 20`; } -function createShardQueryImmediate(path: string, sortOrder?: SortOrder[], tenantName?: string) { - const pathSelect = tenantName - ? `CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path` - : 'Path'; +function createShardQueryImmediate(path: string, database: string, sortOrder?: SortOrder[]) { + const pathSelect = `CAST(SUBSTRING(CAST(Path AS String), ${database.length}) AS Utf8) AS Path`; const orderBy = prepareOrderByFromTableSort(sortOrder); - return `SELECT + return `${QUERY_TECHNICAL_MARK} +SELECT ${pathSelect}, TabletId, CPUCores, @@ -110,7 +109,7 @@ export const {setShardsQueryFilters} = slice.actions; export default slice.reducer; interface SendShardQueryParams { - database?: string; + database: string; path?: string; sortOrder?: SortOrder[]; filters?: ShardsWorkloadFilters; @@ -128,12 +127,12 @@ export const shardApi = api.injectEndpoints({ { query: filters?.mode === EShardsWorkloadMode.Immediate - ? createShardQueryImmediate(path, sortOrder, database) + ? createShardQueryImmediate(path, database, sortOrder) : createShardQueryHistorical( path, + database, filters, sortOrder, - database, ), database, action: queryAction, diff --git a/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts b/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts index 068140da4..83ed2ea20 100644 --- a/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts +++ b/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts @@ -1,27 +1,27 @@ -import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants'; +import {QUERY_TECHNICAL_MARK, TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants'; import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../../utils/query'; import {api} from '../../api'; -const getQueryText = (path: string) => { - return ` +const getQueryText = () => { + return `${QUERY_TECHNICAL_MARK} SELECT Path, SUM(DataSize) as Size -FROM \`${path}/.sys/partition_stats\` +FROM \`.sys/partition_stats\` GROUP BY Path - ORDER BY Size DESC - LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT} +ORDER BY Size DESC +LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT} `; }; export const topTablesApi = api.injectEndpoints({ endpoints: (builder) => ({ getTopTables: builder.query({ - queryFn: async ({path}: {path: string}, {signal}) => { + queryFn: async ({database}: {database: string}, {signal}) => { try { const response = await window.api.viewer.sendQuery( { - query: getQueryText(path), - database: path, + query: getQueryText(), + database, action: 'execute-scan', }, {signal, withRetries: true}, diff --git a/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts b/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts index c37961066..d5638147c 100644 --- a/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts +++ b/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts @@ -1,13 +1,11 @@ -import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants'; +import {QUERY_TECHNICAL_MARK, TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants'; import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../../utils/query'; import {api} from '../../api'; -function createShardQuery(path: string, tenantName?: string) { - const pathSelect = tenantName - ? `CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path` - : 'Path'; - - return `SELECT +function createShardQuery(path: string, database: string) { + const pathSelect = `CAST(SUBSTRING(CAST(Path AS String), ${database.length}) AS Utf8) AS Path`; + return `${QUERY_TECHNICAL_MARK} +SELECT ${pathSelect}, TabletId, CPUCores, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 98957ef76..17aeba8e8 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -52,6 +52,8 @@ export const TENANT_OVERVIEW_TABLES_LIMIT = 5; export const EMPTY_DATA_PLACEHOLDER = '—'; +export const QUERY_TECHNICAL_MARK = '/*UI-QUERY-EXCLUDE*/'; + // ==== Titles ==== export const DEVELOPER_UI_TITLE = 'Developer UI'; export const CLUSTER_DEFAULT_TITLE = 'Cluster';