@parca/profile 0.19.139 → 0.19.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +11 -13
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +4 -9
- package/dist/ProfileFlameChart/SamplesStrips/index.d.ts +2 -2
- package/dist/ProfileFlameChart/SamplesStrips/index.d.ts.map +1 -1
- package/dist/ProfileFlameChart/index.d.ts.map +1 -1
- package/dist/ProfileFlameChart/index.js +13 -19
- package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +8 -8
- package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +4 -3
- package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/index.js +6 -4
- package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
- package/dist/ProfileMetricsGraph/index.js +4 -6
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +5 -10
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +27 -25
- package/dist/ProfileView/components/ActionButtons/SortByDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +5 -5
- package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileView/components/ColorStackLegend.js +2 -3
- package/dist/ProfileView/components/InvertCallStack/index.d.ts.map +1 -1
- package/dist/ProfileView/components/InvertCallStack/index.js +5 -4
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts +1 -2
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts.map +1 -1
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +14 -16
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.js +84 -170
- package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +16 -20
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +4 -5
- package/dist/ProfileView/components/Toolbars/index.d.ts +2 -2
- package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/index.js +1 -1
- package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -1
- package/dist/ProfileView/components/ViewSelector/index.js +8 -14
- package/dist/ProfileView/context/DashboardContext.d.ts.map +1 -1
- package/dist/ProfileView/context/DashboardContext.js +6 -6
- package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetFlameGraphState.js +5 -4
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +25 -26
- package/dist/ProfileView/hooks/useResetStateOnSeriesChange.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +13 -8
- package/dist/ProfileView/hooks/useVisualizationState.d.ts +3 -3
- package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useVisualizationState.js +35 -51
- package/dist/ProfileViewWithData.d.ts.map +1 -1
- package/dist/ProfileViewWithData.js +19 -28
- package/dist/Sandwich/index.d.ts.map +1 -1
- package/dist/Sandwich/index.js +4 -3
- package/dist/SourceView/index.d.ts.map +1 -1
- package/dist/SourceView/index.js +4 -2
- package/dist/SourceView/useSelectedLineRange.d.ts.map +1 -1
- package/dist/SourceView/useSelectedLineRange.js +21 -16
- package/dist/Table/MoreDropdown.d.ts.map +1 -1
- package/dist/Table/MoreDropdown.js +8 -11
- package/dist/Table/TableContextMenu.d.ts.map +1 -1
- package/dist/Table/TableContextMenu.js +10 -13
- package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
- package/dist/Table/hooks/useTableConfiguration.js +3 -4
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +11 -9
- package/dist/TopTable/index.d.ts.map +1 -1
- package/dist/TopTable/index.js +3 -4
- package/dist/hooks/urlParsers.d.ts +18 -0
- package/dist/hooks/urlParsers.d.ts.map +1 -0
- package/dist/hooks/urlParsers.js +32 -0
- package/dist/hooks/useColorBy.d.ts +5 -0
- package/dist/hooks/useColorBy.d.ts.map +1 -0
- package/dist/hooks/useColorBy.js +26 -0
- package/dist/hooks/useCompareModeMeta.d.ts.map +1 -1
- package/dist/hooks/useCompareModeMeta.js +55 -86
- package/dist/hooks/useDashboardItems.d.ts +5 -0
- package/dist/hooks/useDashboardItems.d.ts.map +1 -0
- package/dist/hooks/useDashboardItems.js +27 -0
- package/dist/hooks/useQueryState.d.ts +3 -3
- package/dist/hooks/useQueryState.d.ts.map +1 -1
- package/dist/hooks/useQueryState.js +105 -105
- package/dist/hooks/useQueryState.test.js +186 -302
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -12
- package/dist/useSumBy.d.ts +1 -1
- package/dist/useSumBy.d.ts.map +1 -1
- package/dist/useSumBy.js +2 -2
- package/package.json +8 -7
- package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +11 -13
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +4 -9
- package/src/ProfileFlameChart/SamplesStrips/index.tsx +2 -2
- package/src/ProfileFlameChart/index.tsx +21 -28
- package/src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx +10 -9
- package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +5 -3
- package/src/ProfileFlameGraph/index.tsx +6 -9
- package/src/ProfileMetricsGraph/index.tsx +6 -8
- package/src/ProfileSelector/MetricsGraphSection.tsx +5 -10
- package/src/ProfileSelector/index.tsx +32 -31
- package/src/ProfileView/components/ActionButtons/SortByDropdown.tsx +10 -6
- package/src/ProfileView/components/ColorStackLegend.tsx +2 -4
- package/src/ProfileView/components/InvertCallStack/index.tsx +5 -4
- package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.tsx +94 -192
- package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts +21 -21
- package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +24 -25
- package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +4 -5
- package/src/ProfileView/components/Toolbars/index.tsx +3 -3
- package/src/ProfileView/components/ViewSelector/index.tsx +9 -16
- package/src/ProfileView/context/DashboardContext.tsx +6 -6
- package/src/ProfileView/hooks/useResetFlameGraphState.ts +6 -4
- package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +24 -26
- package/src/ProfileView/hooks/useResetStateOnSeriesChange.ts +16 -8
- package/src/ProfileView/hooks/useVisualizationState.ts +61 -69
- package/src/ProfileViewWithData.tsx +29 -35
- package/src/Sandwich/index.tsx +4 -3
- package/src/SourceView/index.tsx +4 -2
- package/src/SourceView/useSelectedLineRange.ts +34 -19
- package/src/Table/MoreDropdown.tsx +9 -11
- package/src/Table/TableContextMenu.tsx +10 -13
- package/src/Table/hooks/useTableConfiguration.tsx +3 -4
- package/src/Table/index.tsx +12 -21
- package/src/TopTable/index.tsx +3 -4
- package/src/hooks/urlParsers.ts +38 -0
- package/src/hooks/useColorBy.ts +42 -0
- package/src/hooks/useCompareModeMeta.ts +61 -91
- package/src/hooks/useDashboardItems.ts +46 -0
- package/src/hooks/useQueryState.test.tsx +275 -345
- package/src/hooks/useQueryState.ts +136 -118
- package/src/index.tsx +16 -15
- package/src/useSumBy.ts +3 -3
|
@@ -16,8 +16,8 @@ import React, {useCallback, useEffect, useRef, useState} from 'react';
|
|
|
16
16
|
import {Menu} from '@headlessui/react';
|
|
17
17
|
import {Icon} from '@iconify/react';
|
|
18
18
|
import cx from 'classnames';
|
|
19
|
+
import {useQueryState} from 'nuqs';
|
|
19
20
|
|
|
20
|
-
import {useURLState} from '@parca/components';
|
|
21
21
|
import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
|
|
22
22
|
import {ProfileType} from '@parca/parser';
|
|
23
23
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
FIELD_LOCATION_ADDRESS,
|
|
28
28
|
FIELD_MAPPING_FILE,
|
|
29
29
|
} from '../../../ProfileFlameGraph/FlameGraphArrow';
|
|
30
|
+
import {boolParam, hiddenBinariesParser, stringParam} from '../../../hooks/urlParsers';
|
|
30
31
|
import {useProfileViewContext} from '../../context/ProfileViewContext';
|
|
31
32
|
import SwitchMenuItem from './SwitchMenuItem';
|
|
32
33
|
|
|
@@ -206,14 +207,15 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
206
207
|
}) => {
|
|
207
208
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
208
209
|
const [shouldOpenLeft, setShouldOpenLeft] = useState(false);
|
|
209
|
-
const [storeSortBy] =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
const [storeSortBy] = useQueryState('sort_by', stringParam.withDefault(FIELD_FUNCTION_NAME));
|
|
211
|
+
const [colorStackLegend, setStoreColorStackLegend] = useQueryState(
|
|
212
|
+
'color_stack_legend',
|
|
213
|
+
stringParam
|
|
214
|
+
);
|
|
215
|
+
const [hiddenBinaries, setHiddenBinaries] = useQueryState(
|
|
216
|
+
'hidden_binaries',
|
|
217
|
+
hiddenBinariesParser
|
|
218
|
+
);
|
|
217
219
|
const {compareMode} = useProfileViewContext();
|
|
218
220
|
const [colorProfileName] = useUserPreference<string>(
|
|
219
221
|
USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
|
|
@@ -223,11 +225,10 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
223
225
|
|
|
224
226
|
// By default, we want delta profiles (CPU) to be relatively compared.
|
|
225
227
|
// For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
|
|
226
|
-
const compareAbsoluteDefault = profileType?.delta === false
|
|
228
|
+
const compareAbsoluteDefault = profileType?.delta === false;
|
|
227
229
|
|
|
228
|
-
const [compareAbsolute
|
|
229
|
-
|
|
230
|
-
const isCompareAbsolute = compareAbsolute === 'true';
|
|
230
|
+
const [compareAbsolute, setCompareAbsolute] = useQueryState('compare_absolute', boolParam);
|
|
231
|
+
const isCompareAbsolute = compareAbsolute ?? compareAbsoluteDefault;
|
|
231
232
|
|
|
232
233
|
useEffect(() => {
|
|
233
234
|
const checkOverflow = (): void => {
|
|
@@ -248,20 +249,20 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
248
249
|
}, [isTableVizOnly]);
|
|
249
250
|
|
|
250
251
|
const handleBinaryToggle = (index: number): void => {
|
|
251
|
-
const updatedBinaries = [...
|
|
252
|
+
const updatedBinaries = [...hiddenBinaries];
|
|
252
253
|
updatedBinaries.splice(index, 1);
|
|
253
|
-
setHiddenBinaries(updatedBinaries);
|
|
254
|
+
void setHiddenBinaries(updatedBinaries);
|
|
254
255
|
};
|
|
255
256
|
|
|
256
257
|
const setColorStackLegend = useCallback(
|
|
257
258
|
(value: string): void => {
|
|
258
|
-
setStoreColorStackLegend(value);
|
|
259
|
+
void setStoreColorStackLegend(value);
|
|
259
260
|
},
|
|
260
261
|
[setStoreColorStackLegend]
|
|
261
262
|
);
|
|
262
263
|
|
|
263
264
|
const resetLegend = (): void => {
|
|
264
|
-
setHiddenBinaries([]);
|
|
265
|
+
void setHiddenBinaries([]);
|
|
265
266
|
};
|
|
266
267
|
|
|
267
268
|
const menuItems: MenuItemType[] = [
|
|
@@ -329,7 +330,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
329
330
|
},
|
|
330
331
|
{
|
|
331
332
|
label: isCompareAbsolute ? 'Compare Relative' : 'Compare Absolute',
|
|
332
|
-
onclick: () => setCompareAbsolute(isCompareAbsolute
|
|
333
|
+
onclick: () => void setCompareAbsolute(!isCompareAbsolute),
|
|
333
334
|
hide: !compareMode,
|
|
334
335
|
icon: isCompareAbsolute ? 'fluent-mdl2:compare' : 'fluent-mdl2:compare-uneven',
|
|
335
336
|
},
|
|
@@ -359,7 +360,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
359
360
|
},
|
|
360
361
|
{
|
|
361
362
|
label: 'Reset Legend',
|
|
362
|
-
hide: hiddenBinaries
|
|
363
|
+
hide: hiddenBinaries.length === 0,
|
|
363
364
|
onclick: () => resetLegend(),
|
|
364
365
|
id: 'h-reset-legend-button',
|
|
365
366
|
icon: 'system-uicons:reset',
|
|
@@ -367,7 +368,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
367
368
|
{
|
|
368
369
|
label: 'Hidden Binaries',
|
|
369
370
|
id: 'h-hidden-binaries',
|
|
370
|
-
items:
|
|
371
|
+
items: hiddenBinaries.map((binary, index) => ({
|
|
371
372
|
label: binary,
|
|
372
373
|
customSubmenu: (
|
|
373
374
|
<div className="flex items-center gap-2 w-full">
|
|
@@ -383,7 +384,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
383
384
|
</div>
|
|
384
385
|
),
|
|
385
386
|
})),
|
|
386
|
-
hide: hiddenBinaries
|
|
387
|
+
hide: hiddenBinaries.length === 0,
|
|
387
388
|
icon: 'ph:eye-closed',
|
|
388
389
|
},
|
|
389
390
|
];
|
|
@@ -424,10 +425,8 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
424
425
|
{...item}
|
|
425
426
|
onSelect={onSelect}
|
|
426
427
|
closeDropdown={close}
|
|
427
|
-
activeValueForSortBy={storeSortBy
|
|
428
|
-
activeValueForColorBy={
|
|
429
|
-
colorBy === undefined || colorBy === '' ? 'binary' : colorBy
|
|
430
|
-
}
|
|
428
|
+
activeValueForSortBy={storeSortBy}
|
|
429
|
+
activeValueForColorBy={colorBy}
|
|
431
430
|
activeValuesForLevel={groupBy}
|
|
432
431
|
renderAsDiv={item.renderAsDiv}
|
|
433
432
|
/>
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
import {useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {createColumnHelper, type ColumnDef} from '@tanstack/table-core';
|
|
17
|
+
import {useQueryState} from 'nuqs';
|
|
17
18
|
|
|
18
|
-
import {useURLState} from '@parca/components';
|
|
19
19
|
import {ProfileType} from '@parca/parser';
|
|
20
20
|
import {valueFormatter} from '@parca/utilities';
|
|
21
21
|
|
|
22
22
|
import {Row} from '../../../Table';
|
|
23
23
|
import ColumnsVisibility from '../../../Table/ColumnsVisibility';
|
|
24
24
|
import {ColumnName, addPlusSign, getRatioString} from '../../../Table/utils/functions';
|
|
25
|
+
import {tableColumnsParser} from '../../../hooks/urlParsers';
|
|
25
26
|
import {useProfileViewContext} from '../../context/ProfileViewContext';
|
|
26
27
|
|
|
27
28
|
interface Props {
|
|
@@ -32,9 +33,7 @@ interface Props {
|
|
|
32
33
|
|
|
33
34
|
const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Element => {
|
|
34
35
|
const {compareMode} = useProfileViewContext();
|
|
35
|
-
const [tableColumns, setTableColumns] =
|
|
36
|
-
alwaysReturnArray: true,
|
|
37
|
-
});
|
|
36
|
+
const [tableColumns, setTableColumns] = useQueryState('table_columns', tableColumnsParser);
|
|
38
37
|
|
|
39
38
|
const columnHelper = createColumnHelper<Row>();
|
|
40
39
|
|
|
@@ -190,7 +189,7 @@ const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Elemen
|
|
|
190
189
|
const newTableColumns = (Object.keys(updatedColumns) as ColumnName[]).filter(
|
|
191
190
|
col => updatedColumns[col]
|
|
192
191
|
);
|
|
193
|
-
setTableColumns(newTableColumns);
|
|
192
|
+
void setTableColumns(newTableColumns);
|
|
194
193
|
};
|
|
195
194
|
|
|
196
195
|
return (
|
|
@@ -50,7 +50,7 @@ export interface VisualisationToolbarProps {
|
|
|
50
50
|
flamechartDimension: string[];
|
|
51
51
|
setFlamechartDimension: (labels: string[]) => void;
|
|
52
52
|
showVisualizationSelector?: boolean;
|
|
53
|
-
sandwichFunctionName
|
|
53
|
+
sandwichFunctionName: string | null;
|
|
54
54
|
alignFunctionName: string;
|
|
55
55
|
setAlignFunctionName: (align: string) => void;
|
|
56
56
|
colorBy: string;
|
|
@@ -75,7 +75,7 @@ export interface FlameGraphToolbarProps {
|
|
|
75
75
|
|
|
76
76
|
export interface SandwichFlameGraphToolbarProps {
|
|
77
77
|
resetSandwichFunctionName: () => void;
|
|
78
|
-
sandwichFunctionName
|
|
78
|
+
sandwichFunctionName: string | null;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
export const TableToolbar: FC<TableToolbarProps> = ({profileType, total, filtered}) => {
|
|
@@ -120,7 +120,7 @@ export const SandwichFlameGraphToolbar: FC<SandwichFlameGraphToolbarProps> = ({
|
|
|
120
120
|
onClick={() => resetSandwichFunctionName()}
|
|
121
121
|
className="w-auto"
|
|
122
122
|
variant="neutral"
|
|
123
|
-
disabled={sandwichFunctionName
|
|
123
|
+
disabled={sandwichFunctionName == null || sandwichFunctionName.length === 0}
|
|
124
124
|
>
|
|
125
125
|
Reset view
|
|
126
126
|
</Button>
|
|
@@ -13,9 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
import {ReactNode} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {useQueryState} from 'nuqs';
|
|
17
|
+
|
|
18
|
+
import {useParcaContext} from '@parca/components';
|
|
17
19
|
|
|
18
20
|
import {ProfileSource} from '../../../ProfileSource';
|
|
21
|
+
import {stringParam} from '../../../hooks/urlParsers';
|
|
22
|
+
import {useDashboardItems} from '../../../hooks/useDashboardItems';
|
|
19
23
|
import Dropdown, {DropdownElement, InnerAction} from './Dropdown';
|
|
20
24
|
|
|
21
25
|
interface Props {
|
|
@@ -23,15 +27,9 @@ interface Props {
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
const ViewSelector = ({profileSource}: Props): JSX.Element => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
alwaysReturnArray: true,
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
const [, setSandwichFunctionName] = useURLState<string | undefined>('sandwich_function_name');
|
|
30
|
+
const {dashboardItems, setDashboardItems} = useDashboardItems();
|
|
31
|
+
const [, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam);
|
|
33
32
|
const {enableSourcesView, enableSandwichView} = useParcaContext();
|
|
34
|
-
const batchUpdates = useURLStateBatch();
|
|
35
33
|
|
|
36
34
|
const allItems: Array<{
|
|
37
35
|
key: string;
|
|
@@ -129,14 +127,9 @@ const ViewSelector = ({profileSource}: Props): JSX.Element => {
|
|
|
129
127
|
} else {
|
|
130
128
|
const newDashboardItems = dashboardItems.filter(v => v !== item.key);
|
|
131
129
|
|
|
132
|
-
|
|
130
|
+
setDashboardItems(newDashboardItems);
|
|
133
131
|
if (item.key === 'sandwich') {
|
|
134
|
-
|
|
135
|
-
setDashboardItems(newDashboardItems);
|
|
136
|
-
setSandwichFunctionName(undefined);
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
setDashboardItems(newDashboardItems);
|
|
132
|
+
void setSandwichFunctionName(null);
|
|
140
133
|
}
|
|
141
134
|
}
|
|
142
135
|
},
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
import {FC, PropsWithChildren, createContext, useContext} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {useQueryState} from 'nuqs';
|
|
17
17
|
|
|
18
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
19
|
+
import {useDashboardItems} from '../../hooks/useDashboardItems';
|
|
18
20
|
import {VisualizationType} from '../types/visualization';
|
|
19
21
|
|
|
20
22
|
interface DashboardContextType {
|
|
@@ -27,10 +29,8 @@ interface DashboardContextType {
|
|
|
27
29
|
const DashboardContext = createContext<DashboardContextType | undefined>(undefined);
|
|
28
30
|
|
|
29
31
|
export const DashboardProvider: FC<PropsWithChildren> = ({children}) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
const [, setSandwichFunctionName] = useURLState<string | undefined>('sandwich_function_name');
|
|
32
|
+
const {dashboardItems, setDashboardItems} = useDashboardItems();
|
|
33
|
+
const [, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam);
|
|
34
34
|
|
|
35
35
|
const handleClosePanel = (visualizationType: VisualizationType): void => {
|
|
36
36
|
const newDashboardItems = dashboardItems.filter(item => item !== visualizationType);
|
|
@@ -38,7 +38,7 @@ export const DashboardProvider: FC<PropsWithChildren> = ({children}) => {
|
|
|
38
38
|
|
|
39
39
|
// Reset sandwich function name when closing sandwich panel
|
|
40
40
|
if (visualizationType === 'sandwich') {
|
|
41
|
-
setSandwichFunctionName(
|
|
41
|
+
void setSandwichFunctionName(null);
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -11,17 +11,19 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryState} from 'nuqs';
|
|
15
|
+
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
15
17
|
|
|
16
18
|
export const useResetFlameGraphState = (): (() => void) => {
|
|
17
|
-
const [val, setCurPath] =
|
|
19
|
+
const [val, setCurPath] = useQueryState('cur_path', stringParam);
|
|
18
20
|
|
|
19
21
|
return () => {
|
|
20
22
|
setTimeout(() => {
|
|
21
|
-
if (val ===
|
|
23
|
+
if (val === null) {
|
|
22
24
|
return;
|
|
23
25
|
}
|
|
24
|
-
setCurPath(
|
|
26
|
+
void setCurPath(null);
|
|
25
27
|
});
|
|
26
28
|
};
|
|
27
29
|
};
|
|
@@ -11,39 +11,37 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryStates} from 'nuqs';
|
|
15
15
|
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
16
17
|
import {useProfileFilters} from '../components/ProfileFilters/useProfileFilters';
|
|
17
18
|
|
|
18
19
|
export const useResetStateOnProfileTypeChange = (): (() => void) => {
|
|
19
|
-
const [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const [state, setState] = useQueryStates(
|
|
21
|
+
{
|
|
22
|
+
group_by: stringParam,
|
|
23
|
+
cur_path: stringParam,
|
|
24
|
+
sum_by_a: stringParam,
|
|
25
|
+
sum_by_b: stringParam,
|
|
26
|
+
sandwich_function_name: stringParam,
|
|
27
|
+
},
|
|
28
|
+
{history: 'replace'}
|
|
29
|
+
);
|
|
23
30
|
const {resetFilters} = useProfileFilters();
|
|
24
|
-
const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
|
|
25
|
-
const batchUpdates = useURLStateBatch();
|
|
26
31
|
|
|
27
32
|
return () => {
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
if (sandwichFunctionName !== undefined) {
|
|
37
|
-
setSandwichFunctionName(undefined);
|
|
38
|
-
}
|
|
39
|
-
if (sumByA !== undefined) {
|
|
40
|
-
setSumByA(undefined);
|
|
41
|
-
}
|
|
42
|
-
if (sumByB !== undefined) {
|
|
43
|
-
setSumByB(undefined);
|
|
44
|
-
}
|
|
33
|
+
// Atomic reset: clear all params in single URL update
|
|
34
|
+
const updates: Record<string, null> = {};
|
|
35
|
+
if (state.group_by !== null) updates.group_by = null;
|
|
36
|
+
if (state.cur_path !== null) updates.cur_path = null;
|
|
37
|
+
if (state.sandwich_function_name !== null) updates.sandwich_function_name = null;
|
|
38
|
+
if (state.sum_by_a !== null) updates.sum_by_a = null;
|
|
39
|
+
if (state.sum_by_b !== null) updates.sum_by_b = null;
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
if (Object.keys(updates).length > 0) {
|
|
42
|
+
void setState(updates);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
resetFilters();
|
|
48
46
|
};
|
|
49
47
|
};
|
|
@@ -11,19 +11,27 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryStates} from 'nuqs';
|
|
15
|
+
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
15
17
|
|
|
16
18
|
export const useResetStateOnSeriesChange = (): (() => void) => {
|
|
17
|
-
const [
|
|
18
|
-
|
|
19
|
+
const [state, setState] = useQueryStates(
|
|
20
|
+
{
|
|
21
|
+
cur_path: stringParam,
|
|
22
|
+
sandwich_function_name: stringParam,
|
|
23
|
+
},
|
|
24
|
+
{history: 'replace'}
|
|
25
|
+
);
|
|
19
26
|
|
|
20
27
|
return () => {
|
|
21
28
|
setTimeout(() => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const updates: Record<string, null> = {};
|
|
30
|
+
if (state.cur_path !== null) updates.cur_path = null;
|
|
31
|
+
if (state.sandwich_function_name !== null) updates.sandwich_function_name = null;
|
|
32
|
+
|
|
33
|
+
if (Object.keys(updates).length > 0) {
|
|
34
|
+
void setState(updates);
|
|
27
35
|
}
|
|
28
36
|
});
|
|
29
37
|
};
|
|
@@ -13,13 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import {useCallback, useMemo} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
JSONSerializer,
|
|
19
|
-
useURLState,
|
|
20
|
-
useURLStateBatch,
|
|
21
|
-
useURLStateCustom,
|
|
22
|
-
} from '@parca/components';
|
|
16
|
+
import {useQueryState} from 'nuqs';
|
|
17
|
+
|
|
23
18
|
import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
|
|
24
19
|
|
|
25
20
|
import {
|
|
@@ -30,12 +25,19 @@ import {
|
|
|
30
25
|
FIELD_MAPPING_FILE,
|
|
31
26
|
} from '../../ProfileFlameGraph/FlameGraphArrow';
|
|
32
27
|
import {CurrentPathFrame} from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
28
|
+
import {
|
|
29
|
+
flamechartDimensionParser,
|
|
30
|
+
groupByParser,
|
|
31
|
+
jsonParser,
|
|
32
|
+
stringParam,
|
|
33
|
+
} from '../../hooks/urlParsers';
|
|
34
|
+
import {useColorBy} from '../../hooks/useColorBy';
|
|
33
35
|
import {useResetFlameGraphState} from './useResetFlameGraphState';
|
|
34
36
|
|
|
35
37
|
export const useVisualizationState = (): {
|
|
36
38
|
curPathArrow: CurrentPathFrame[];
|
|
37
39
|
setCurPathArrow: (path: CurrentPathFrame[]) => void;
|
|
38
|
-
colorStackLegend: string |
|
|
40
|
+
colorStackLegend: string | null;
|
|
39
41
|
colorBy: string;
|
|
40
42
|
setColorBy: (colorBy: string) => void;
|
|
41
43
|
groupBy: string[];
|
|
@@ -44,46 +46,52 @@ export const useVisualizationState = (): {
|
|
|
44
46
|
setGroupByLabels: (labels: string[]) => void;
|
|
45
47
|
flamechartDimension: string[];
|
|
46
48
|
setFlamechartDimension: (labels: string[]) => void;
|
|
47
|
-
sandwichFunctionName: string |
|
|
48
|
-
setSandwichFunctionName: (sandwichFunctionName: string |
|
|
49
|
+
sandwichFunctionName: string | null;
|
|
50
|
+
setSandwichFunctionName: (sandwichFunctionName: string | null) => void;
|
|
49
51
|
resetSandwichFunctionName: () => void;
|
|
50
52
|
alignFunctionName: string;
|
|
51
53
|
setAlignFunctionName: (align: string) => void;
|
|
52
54
|
} => {
|
|
53
|
-
const [colorByPreference, setColorByPreference] = useUserPreference<string>(
|
|
54
|
-
USER_PREFERENCES.COLOR_BY.key
|
|
55
|
-
);
|
|
56
55
|
const [alignFunctionNamePreference, setAlignFunctionNamePreference] = useUserPreference<string>(
|
|
57
56
|
USER_PREFERENCES.ALIGN_FUNCTION_NAME.key
|
|
58
57
|
);
|
|
59
58
|
|
|
60
|
-
const [curPathArrow,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
const [
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
59
|
+
const [curPathArrow, setRawCurPathArrow] = useQueryState(
|
|
60
|
+
'cur_path',
|
|
61
|
+
jsonParser<CurrentPathFrame[]>().withDefault([])
|
|
62
|
+
);
|
|
63
|
+
const setCurPathArrow = useCallback(
|
|
64
|
+
(path: CurrentPathFrame[]) => {
|
|
65
|
+
void setRawCurPathArrow(path);
|
|
66
|
+
},
|
|
67
|
+
[setRawCurPathArrow]
|
|
68
|
+
);
|
|
69
|
+
const [colorStackLegend] = useQueryState('color_stack_legend', stringParam);
|
|
70
|
+
const {colorBy, setColorBy} = useColorBy();
|
|
71
|
+
const [alignFunctionNameRaw, setStoreAlignFunctionName] = useQueryState(
|
|
72
|
+
'align_function_name',
|
|
73
|
+
stringParam
|
|
74
|
+
);
|
|
75
|
+
const alignFunctionName = alignFunctionNameRaw ?? alignFunctionNamePreference ?? 'left';
|
|
76
|
+
const [groupBy, setStoreGroupBy] = useQueryState(
|
|
77
|
+
'group_by',
|
|
78
|
+
groupByParser.withDefault([FIELD_FUNCTION_NAME])
|
|
79
|
+
);
|
|
80
|
+
const [sandwichFunctionName, setRawSandwichFunctionName] = useQueryState(
|
|
81
|
+
'sandwich_function_name',
|
|
82
|
+
stringParam
|
|
78
83
|
);
|
|
79
|
-
const
|
|
84
|
+
const setSandwichFunctionName = useCallback(
|
|
85
|
+
(name: string | null) => {
|
|
86
|
+
void setRawSandwichFunctionName(name);
|
|
87
|
+
},
|
|
88
|
+
[setRawSandwichFunctionName]
|
|
89
|
+
);
|
|
90
|
+
const [flamechartDimension, setStoreFlamechartDimension] = useQueryState(
|
|
80
91
|
'flamechart_dimension',
|
|
81
|
-
|
|
82
|
-
alwaysReturnArray: true,
|
|
83
|
-
}
|
|
92
|
+
flamechartDimensionParser.withDefault([])
|
|
84
93
|
);
|
|
85
94
|
const resetFlameGraphState = useResetFlameGraphState();
|
|
86
|
-
const batchUpdates = useURLStateBatch();
|
|
87
95
|
|
|
88
96
|
const levelsOfProfiling = useMemo(
|
|
89
97
|
() => [
|
|
@@ -97,62 +105,46 @@ export const useVisualizationState = (): {
|
|
|
97
105
|
|
|
98
106
|
const setGroupBy = useCallback(
|
|
99
107
|
(keys: string[]): void => {
|
|
100
|
-
setStoreGroupBy(keys);
|
|
108
|
+
void setStoreGroupBy(keys);
|
|
101
109
|
},
|
|
102
110
|
[setStoreGroupBy]
|
|
103
111
|
);
|
|
104
112
|
|
|
105
113
|
const toggleGroupBy = useCallback(
|
|
106
114
|
(key: string): void => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
resetFlameGraphState();
|
|
117
|
-
});
|
|
115
|
+
if (groupBy.includes(key)) {
|
|
116
|
+
setGroupBy(groupBy.filter(v => v !== key));
|
|
117
|
+
} else {
|
|
118
|
+
const filteredGroupBy = groupBy.filter(item => !levelsOfProfiling.includes(item));
|
|
119
|
+
setGroupBy([...filteredGroupBy, key]);
|
|
120
|
+
}
|
|
121
|
+
resetFlameGraphState();
|
|
118
122
|
},
|
|
119
|
-
[groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState
|
|
123
|
+
[groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState]
|
|
120
124
|
);
|
|
121
125
|
|
|
122
126
|
const setGroupByLabels = useCallback(
|
|
123
127
|
(labels: string[]): void => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
|
|
127
|
-
|
|
128
|
-
resetFlameGraphState();
|
|
129
|
-
});
|
|
128
|
+
setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
|
|
129
|
+
resetFlameGraphState();
|
|
130
130
|
},
|
|
131
|
-
[groupBy, setGroupBy, resetFlameGraphState
|
|
131
|
+
[groupBy, setGroupBy, resetFlameGraphState]
|
|
132
132
|
);
|
|
133
133
|
|
|
134
134
|
const setFlamechartDimension = useCallback(
|
|
135
135
|
(labels: string[]): void => {
|
|
136
|
-
setStoreFlamechartDimension(labels.filter(l => l.startsWith(`${FIELD_LABELS}.`)));
|
|
136
|
+
void setStoreFlamechartDimension(labels.filter(l => l.startsWith(`${FIELD_LABELS}.`)));
|
|
137
137
|
},
|
|
138
138
|
[setStoreFlamechartDimension]
|
|
139
139
|
);
|
|
140
140
|
|
|
141
141
|
const resetSandwichFunctionName = useCallback((): void => {
|
|
142
|
-
setSandwichFunctionName(
|
|
142
|
+
setSandwichFunctionName(null);
|
|
143
143
|
}, [setSandwichFunctionName]);
|
|
144
144
|
|
|
145
|
-
const setColorBy = useCallback(
|
|
146
|
-
(value: string): void => {
|
|
147
|
-
setStoreColorBy(value);
|
|
148
|
-
setColorByPreference(value);
|
|
149
|
-
},
|
|
150
|
-
[setStoreColorBy, setColorByPreference]
|
|
151
|
-
);
|
|
152
|
-
|
|
153
145
|
const setAlignFunctionName = useCallback(
|
|
154
146
|
(value: string): void => {
|
|
155
|
-
setStoreAlignFunctionName(value);
|
|
147
|
+
void setStoreAlignFunctionName(value);
|
|
156
148
|
setAlignFunctionNamePreference(value);
|
|
157
149
|
},
|
|
158
150
|
[setStoreAlignFunctionName, setAlignFunctionNamePreference]
|
|
@@ -162,7 +154,7 @@ export const useVisualizationState = (): {
|
|
|
162
154
|
curPathArrow,
|
|
163
155
|
setCurPathArrow,
|
|
164
156
|
colorStackLegend,
|
|
165
|
-
colorBy
|
|
157
|
+
colorBy,
|
|
166
158
|
setColorBy,
|
|
167
159
|
groupBy,
|
|
168
160
|
setGroupBy,
|
|
@@ -173,7 +165,7 @@ export const useVisualizationState = (): {
|
|
|
173
165
|
sandwichFunctionName,
|
|
174
166
|
setSandwichFunctionName,
|
|
175
167
|
resetSandwichFunctionName,
|
|
176
|
-
alignFunctionName
|
|
168
|
+
alignFunctionName,
|
|
177
169
|
setAlignFunctionName,
|
|
178
170
|
};
|
|
179
171
|
};
|