Skip to content

Commit 1fb9078

Browse files
authored
feat: cpu info toggle – display top queries for last hour (#1049)
1 parent bce4e92 commit 1fb9078

File tree

12 files changed

+80
-81
lines changed

12 files changed

+80
-81
lines changed

src/components/DateRange/DateRange.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ export interface DateRangeValues {
1919
to?: string;
2020
}
2121

22+
const DEFAULT_VALUE = {
23+
start: {
24+
value: 'now-1h',
25+
type: 'relative',
26+
},
27+
end: {
28+
value: 'now',
29+
type: 'relative',
30+
},
31+
} as const;
32+
2233
interface DateRangeProps extends DateRangeValues {
2334
className?: string;
2435
onChange?: (value: DateRangeValues) => void;
@@ -45,7 +56,7 @@ export const DateRange = ({from, to, className, onChange}: DateRangeProps) => {
4556
withPresets
4657
className={b('range-input', {[getdatePickerSize(value)]: true})}
4758
timeZone={timeZoneString}
48-
value={value || null}
59+
value={value || DEFAULT_VALUE}
4960
allowNullableValues
5061
size="m"
5162
format={i18n('date-time-format')}

src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,22 @@ import {useHistory, useLocation} from 'react-router-dom';
44

55
import {parseQuery} from '../../../../../routes';
66
import {changeUserInput} from '../../../../../store/reducers/executeQuery';
7+
import {
8+
setTopQueriesFilters,
9+
topQueriesApi,
10+
} from '../../../../../store/reducers/executeTopQueries/executeTopQueries';
711
import {
812
TENANT_DIAGNOSTICS_TABS_IDS,
913
TENANT_PAGE,
1014
TENANT_PAGES_IDS,
1115
TENANT_QUERY_TABS_ID,
1216
} from '../../../../../store/reducers/tenant/constants';
13-
import {topQueriesApi} from '../../../../../store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries';
1417
import {useAutoRefreshInterval, useTypedDispatch} from '../../../../../utils/hooks';
1518
import {parseQueryErrorToString} from '../../../../../utils/query';
1619
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
1720
import {
21+
TENANT_OVERVIEW_TOP_QUERUES_COLUMNS,
1822
TOP_QUERIES_COLUMNS_WIDTH_LS_KEY,
19-
getTenantOverviewTopQueriesColumns,
2023
} from '../../TopQueries/getTopQueriesColumns';
2124
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
2225
import {getSectionTitle} from '../getSectionTitle';
@@ -35,9 +38,9 @@ export function TopQueries({tenantName}: TopQueriesProps) {
3538
const query = parseQuery(location);
3639

3740
const [autoRefreshInterval] = useAutoRefreshInterval();
38-
const columns = getTenantOverviewTopQueriesColumns();
41+
const columns = TENANT_OVERVIEW_TOP_QUERUES_COLUMNS;
3942

40-
const {currentData, isFetching, error} = topQueriesApi.useGetOverviewTopQueriesQuery(
43+
const {currentData, isFetching, error} = topQueriesApi.useGetTopQueriesQuery(
4144
{database: tenantName},
4245
{pollingInterval: autoRefreshInterval},
4346
);
@@ -66,7 +69,10 @@ export function TopQueries({tenantName}: TopQueriesProps) {
6669

6770
const title = getSectionTitle({
6871
entity: i18n('queries'),
69-
postfix: i18n('by-cpu-time'),
72+
postfix: i18n('by-cpu-time', {executionPeriod: i18n('executed-last-hour')}),
73+
onClick: () => {
74+
dispatch(setTopQueriesFilters({from: undefined, to: undefined}));
75+
},
7076
link: getTenantPath({
7177
...query,
7278
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.topQueries,

src/containers/Tenant/Diagnostics/TenantOverview/getSectionTitle.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface GetSectionTitleParams {
99
postfix: string;
1010
prefix?: string;
1111
link?: string;
12+
onClick?: () => void;
1213
}
1314

1415
// Titles are formed by the principle "Top entities by parameter"
@@ -17,11 +18,16 @@ export const getSectionTitle = ({
1718
entity,
1819
postfix,
1920
link,
21+
onClick,
2022
}: GetSectionTitleParams) => {
2123
if (link) {
2224
return (
2325
<React.Fragment>
24-
{prefix} <InternalLink to={link}>{entity}</InternalLink> {postfix}
26+
{prefix}{' '}
27+
<InternalLink to={link} onClick={onClick}>
28+
{entity}
29+
</InternalLink>{' '}
30+
{postfix}
2531
</React.Fragment>
2632
);
2733
}

src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"tables": "tables",
1515

1616
"by-pools-usage": "by pools usage",
17-
"by-cpu-time": "by cpu time",
17+
"by-cpu-time": "by cpu time, {{executionPeriod}}",
1818
"by-cpu-usage": "by cpu usage",
1919
"by-load": "by load",
2020
"by-memory": "by memory",
@@ -34,5 +34,7 @@
3434
"storage.tablet-storage-title": "Tablet storage",
3535
"storage.tablet-storage-description": "Size of user data and indexes stored in schema objects (tables, topics, etc.)",
3636
"storage.db-storage-title": "Database storage",
37-
"storage.db-storage-description": "Size of data stored in distributed storage with all overheads for redundancy"
37+
"storage.db-storage-description": "Size of data stored in distributed storage with all overheads for redundancy",
38+
39+
"executed-last-hour": "executed in the last hour"
3840
}

src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {TenantTabsGroups, getTenantPath} from '../../TenantPages';
2727
import {QUERY_TABLE_SETTINGS} from '../../utils/constants';
2828
import {isColumnEntityType} from '../../utils/schema';
2929

30-
import {TOP_QUERIES_COLUMNS_WIDTH_LS_KEY, getTopQueriesColumns} from './getTopQueriesColumns';
30+
import {TOP_QUERIES_COLUMNS, TOP_QUERIES_COLUMNS_WIDTH_LS_KEY} from './getTopQueriesColumns';
3131
import i18n from './i18n';
3232

3333
import './TopQueries.scss';
@@ -57,7 +57,7 @@ export const TopQueries = ({tenantName, type}: TopQueriesProps) => {
5757
const loading = isFetching && currentData === undefined;
5858
const {result: data} = currentData || {};
5959

60-
const rawColumns = getTopQueriesColumns();
60+
const rawColumns = TOP_QUERIES_COLUMNS;
6161
const columns = rawColumns.map((column) => ({
6262
...column,
6363
sortable: isSortableTopQueriesProperty(column.name),

src/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,18 @@ const durationColumn: Column<KeyValueRow> = {
9494
width: 150,
9595
};
9696

97-
export const getTopQueriesColumns = (): Column<KeyValueRow>[] => {
98-
return [
99-
cpuTimeUsColumn,
100-
queryTextColumn,
101-
endTimeColumn,
102-
durationColumn,
103-
readRowsColumn,
104-
readBytesColumn,
105-
userSIDColumn,
106-
];
107-
};
97+
export const TOP_QUERIES_COLUMNS = [
98+
cpuTimeUsColumn,
99+
queryTextColumn,
100+
endTimeColumn,
101+
durationColumn,
102+
readRowsColumn,
103+
readBytesColumn,
104+
userSIDColumn,
105+
];
108106

109-
export const getTenantOverviewTopQueriesColumns = (): Column<KeyValueRow>[] => {
110-
return [queryHashColumn, oneLineQueryTextColumn, cpuTimeUsColumn];
111-
};
107+
export const TENANT_OVERVIEW_TOP_QUERUES_COLUMNS = [
108+
queryHashColumn,
109+
oneLineQueryTextColumn,
110+
cpuTimeUsColumn,
111+
];

src/containers/Tenant/TenantPages.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
import routes, {createHref} from '../../routes';
22
import {TENANT_SUMMARY_TABS_IDS} from '../../store/reducers/tenant/constants';
3+
import type {paramSetup} from '../../store/state-url-mapping';
4+
import type {ExtractType} from '../../types/common';
5+
6+
type TenantQueryParams = {
7+
[K in keyof (typeof paramSetup)['/tenant']]?: ExtractType<(typeof paramSetup)['/tenant'][K]>;
8+
};
9+
10+
type AdditionalQueryParams = {
11+
name?: string;
12+
backend?: string;
13+
};
14+
15+
type TenantQuery = TenantQueryParams | AdditionalQueryParams;
316

417
export const TenantTabsGroups = {
518
summaryTab: 'summaryTab',
@@ -26,6 +39,6 @@ export const TENANT_SCHEMA_TAB = [
2639
},
2740
];
2841

29-
export const getTenantPath = (query = {}) => {
42+
export const getTenantPath = (query: TenantQuery) => {
3043
return createHref(routes.tenant, undefined, query);
3144
};

src/routes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ export function createHref(
5959
) {
6060
let extendedQuery = query;
6161

62-
const isBackendInQuery = Boolean(query.backend);
62+
const isBackendInQuery = 'backend' in query && Boolean(query.backend);
6363
if (backend && !isBackendInQuery && webVersion) {
6464
extendedQuery = {...query, backend};
6565
}
6666

67-
const isClusterNameInQuery = Boolean(query.clusterName);
67+
const isClusterNameInQuery = 'clusterName' in query && Boolean(query.clusterName);
6868
if (clusterName && !isClusterNameInQuery && webVersion) {
6969
extendedQuery = {...extendedQuery, clusterName};
7070
}

src/store/reducers/executeTopQueries/executeTopQueries.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,19 @@ export const topQueriesApi = api.injectEndpoints({
4646
getTopQueries: build.query({
4747
queryFn: async (
4848
{database, filters}: {database: string; filters?: TopQueriesFilters},
49-
{signal, dispatch},
49+
{signal},
5050
) => {
51+
const preparedFilters = {
52+
...filters,
53+
from: filters?.from || 'now-1h',
54+
to: filters?.to || 'now',
55+
};
56+
5157
try {
5258
const response = await window.api.sendQuery(
5359
{
5460
schema: 'modern',
55-
query: getQueryText(database, filters),
61+
query: getQueryText(database, preparedFilters),
5662
database,
5763
action: 'execute-scan',
5864
},
@@ -64,17 +70,15 @@ export const topQueriesApi = api.injectEndpoints({
6470
}
6571

6672
const data = parseQueryAPIExecuteResponse(response);
67-
68-
if (!filters?.from && !filters?.to) {
69-
dispatch(setTopQueriesFilters({from: 'now-1h', to: 'now'}));
70-
}
7173
return {data};
7274
} catch (error) {
7375
return {error};
7476
}
7577
},
7678
forceRefetch: ({currentArg}) => {
7779
if (
80+
!currentArg?.filters?.from ||
81+
!currentArg?.filters?.to ||
7882
isLikeRelative(currentArg?.filters?.from) ||
7983
isLikeRelative(currentArg?.filters?.to)
8084
) {

src/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts

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

src/store/state-url-mapping.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {stateToParams} from 'redux-location-state/lib/stateToParams';
1414
import {initialState as initialHeatmapState} from './reducers/heatmap';
1515
import {initialState as initialSettingsState} from './reducers/settings/settings';
1616

17-
const paramSetup: ParamSetup = {
17+
export const paramSetup = {
1818
global: {
1919
problemFilter: {
2020
stateKey: 'settings.problemFilter',
@@ -83,7 +83,7 @@ const paramSetup: ParamSetup = {
8383
stateKey: 'tenants.searchValue',
8484
},
8585
},
86-
};
86+
} as const;
8787

8888
function mergeLocationToState<S>(state: S, location: Pick<LocationWithQuery, 'query'>): S {
8989
return merge({}, state, location.query);
@@ -95,7 +95,7 @@ function restoreUnknownParams(location: Location, prevLocation: Location) {
9595

9696
// figure out which path key inside paramSetup matches location.pathname
9797
const declaredPath = getMatchingDeclaredPath(paramSetup, location);
98-
const entries = declaredPath && paramSetup[declaredPath];
98+
const entries = declaredPath && paramSetup[declaredPath as keyof typeof paramSetup];
9999

100100
// remove params which are mapped for this page
101101
each(keys(entries), (param) => {

src/types/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export type ValueOf<T extends Object> = T[keyof T];
2+
export type ExtractType<T> = T extends {type: infer U} ? U : string;

0 commit comments

Comments
 (0)