@parca/profile 0.16.415 → 0.16.417
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 +8 -0
- package/dist/Callgraph/index.js +3 -2
- package/dist/GraphTooltipArrow/Content.d.ts +1 -3
- package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/Content.js +4 -4
- package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +2 -2
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts +1 -3
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +6 -16
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +3 -3
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +1 -1
- package/dist/ProfileExplorer/index.d.ts.map +1 -1
- package/dist/ProfileExplorer/index.js +1 -7
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +1 -3
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.js +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -2
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/index.js +4 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts +1 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +8 -20
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +1 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +1 -2
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +6 -9
- package/dist/ProfileIcicleGraph/index.d.ts +1 -3
- package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/index.js +20 -48
- package/dist/ProfileMetricsGraph/index.js +1 -2
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +19 -2
- package/dist/ProfileView/FilterByFunctionButton.d.ts +1 -4
- package/dist/ProfileView/FilterByFunctionButton.d.ts.map +1 -1
- package/dist/ProfileView/FilterByFunctionButton.js +12 -3
- package/dist/ProfileView/ViewSelector.d.ts +1 -3
- package/dist/ProfileView/ViewSelector.d.ts.map +1 -1
- package/dist/ProfileView/ViewSelector.js +3 -4
- package/dist/ProfileView/VisualizationPanel.d.ts +0 -2
- package/dist/ProfileView/VisualizationPanel.d.ts.map +1 -1
- package/dist/ProfileView/VisualizationPanel.js +2 -2
- package/dist/ProfileView/index.d.ts +1 -5
- package/dist/ProfileView/index.d.ts.map +1 -1
- package/dist/ProfileView/index.js +11 -18
- package/dist/ProfileViewWithData.d.ts +1 -3
- package/dist/ProfileViewWithData.d.ts.map +1 -1
- package/dist/ProfileViewWithData.js +15 -12
- package/dist/SourceView/index.js +1 -1
- package/dist/SourceView/useSelectedLineRange.js +1 -1
- package/dist/Table/index.d.ts +1 -2
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +9 -25
- package/dist/TopTable/index.d.ts.map +1 -1
- package/dist/TopTable/index.js +3 -7
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/styles.css +1 -1
- package/package.json +7 -7
- package/src/Callgraph/index.tsx +3 -3
- package/src/GraphTooltipArrow/Content.tsx +4 -14
- package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +2 -2
- package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +6 -22
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +2 -3
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -5
- package/src/ProfileExplorer/index.tsx +0 -8
- package/src/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.tsx +2 -4
- package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +5 -8
- package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +8 -27
- package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +2 -4
- package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +4 -17
- package/src/ProfileIcicleGraph/index.tsx +19 -67
- package/src/ProfileMetricsGraph/index.tsx +2 -2
- package/src/ProfileSelector/index.tsx +23 -2
- package/src/ProfileView/FilterByFunctionButton.tsx +15 -9
- package/src/ProfileView/ViewSelector.tsx +6 -7
- package/src/ProfileView/VisualizationPanel.tsx +1 -9
- package/src/ProfileView/index.tsx +8 -23
- package/src/ProfileViewWithData.tsx +15 -18
- package/src/SourceView/index.tsx +1 -1
- package/src/SourceView/useSelectedLineRange.ts +2 -2
- package/src/Table/index.tsx +10 -41
- package/src/TopTable/index.tsx +3 -8
- package/src/index.tsx +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAS1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAS1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAc1C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAyHD,QAAA,MAAM,kBAAkB,6IAcrB,uBAAuB,KAAG,GAAG,CAAC,OAgPhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -16,28 +16,22 @@ import { Icon } from '@iconify/react';
|
|
|
16
16
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
17
17
|
import { Button, IcicleGraphSkeleton, IconButton, useParcaContext, useURLState, } from '@parca/components';
|
|
18
18
|
import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
|
|
19
|
-
import { capitalizeOnlyFirstLetter, divide, selectQueryParam
|
|
19
|
+
import { capitalizeOnlyFirstLetter, divide, selectQueryParam } from '@parca/utilities';
|
|
20
20
|
import { useProfileViewContext } from '../ProfileView/ProfileViewContext';
|
|
21
21
|
import DiffLegend from '../components/DiffLegend';
|
|
22
22
|
import GroupByDropdown from './ActionButtons/GroupByDropdown';
|
|
23
23
|
import SortBySelect from './ActionButtons/SortBySelect';
|
|
24
|
-
import IcicleGraph from './IcicleGraph';
|
|
25
|
-
import
|
|
24
|
+
import { IcicleGraph } from './IcicleGraph';
|
|
25
|
+
import { FIELD_FUNCTION_NAME, IcicleGraphArrow } from './IcicleGraphArrow';
|
|
26
26
|
import ColorStackLegend from './IcicleGraphArrow/ColorStackLegend';
|
|
27
27
|
import useMappingList from './IcicleGraphArrow/useMappingList';
|
|
28
28
|
const numberFormatter = new Intl.NumberFormat('en-US');
|
|
29
29
|
const ErrorContent = ({ errorMessage }) => {
|
|
30
30
|
return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
|
|
31
31
|
};
|
|
32
|
-
const ShowHideLegendButton = ({
|
|
33
|
-
const [colorStackLegend, setStoreColorStackLegend] = useURLState(
|
|
34
|
-
|
|
35
|
-
navigateTo,
|
|
36
|
-
});
|
|
37
|
-
const [binaryFrameFilter, setBinaryFrameFilter] = useURLState({
|
|
38
|
-
param: 'binary_frame_filter',
|
|
39
|
-
navigateTo,
|
|
40
|
-
});
|
|
32
|
+
const ShowHideLegendButton = ({ isHalfScreen }) => {
|
|
33
|
+
const [colorStackLegend, setStoreColorStackLegend] = useURLState('color_stack_legend');
|
|
34
|
+
const [binaryFrameFilter, setBinaryFrameFilter] = useURLState('binary_frame_filter');
|
|
41
35
|
const { compareMode } = useProfileViewContext();
|
|
42
36
|
const isColorStackLegendEnabled = colorStackLegend === 'true';
|
|
43
37
|
const [colorProfileName] = useUserPreference(USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key);
|
|
@@ -49,28 +43,18 @@ const ShowHideLegendButton = ({ navigateTo, isHalfScreen, }) => {
|
|
|
49
43
|
};
|
|
50
44
|
return (_jsx(_Fragment, { children: colorProfileName === 'default' || compareMode ? null : (_jsx(_Fragment, { children: isHalfScreen ? (_jsxs(_Fragment, { children: [_jsx(IconButton, { className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center !py-2 !px-3 cursor-pointer min-h-[38px]", icon: isColorStackLegendEnabled ? 'ph:eye-closed' : 'ph:eye', toolTipText: isColorStackLegendEnabled ? 'Hide legend' : 'Show legend', onClick: () => setColorStackLegend(isColorStackLegendEnabled ? 'false' : 'true'), id: "h-show-legend-button" }), binaryFrameFilter !== undefined && binaryFrameFilter.length > 0 && (_jsx(IconButton, { className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center !py-2 !px-3 cursor-pointer min-h-[38px]", icon: "system-uicons:reset", toolTipText: "Reset the legend selection", onClick: () => resetLegend(), id: "h-reset-legend-button" }))] })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { className: "gap-2 w-max", variant: "neutral", onClick: () => setColorStackLegend(isColorStackLegendEnabled ? 'false' : 'true'), id: "h-show-legend-button", children: [isColorStackLegendEnabled ? 'Hide legend' : 'Show legend', _jsx(Icon, { icon: isColorStackLegendEnabled ? 'ph:eye-closed' : 'ph:eye', width: 20 })] }), binaryFrameFilter !== undefined && binaryFrameFilter.length > 0 && (_jsxs(Button, { className: "gap-2 w-max", variant: "neutral", onClick: () => resetLegend(), id: "h-reset-legend-button", children: ["Reset Legend", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }))] })) })) }));
|
|
51
45
|
};
|
|
52
|
-
const GroupAndSortActionButtons = (
|
|
53
|
-
const [storeSortBy
|
|
54
|
-
|
|
55
|
-
navigateTo,
|
|
46
|
+
const GroupAndSortActionButtons = () => {
|
|
47
|
+
const [storeSortBy, setStoreSortBy] = useURLState('sort_by', {
|
|
48
|
+
defaultValue: FIELD_FUNCTION_NAME,
|
|
56
49
|
});
|
|
57
50
|
const { compareMode } = useProfileViewContext();
|
|
58
|
-
const [
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
const [groupBy, setStoreGroupBy] = useURLState('group_by', {
|
|
52
|
+
defaultValue: [FIELD_FUNCTION_NAME],
|
|
53
|
+
alwaysReturnArray: true,
|
|
61
54
|
});
|
|
62
55
|
const setGroupBy = useCallback((keys) => {
|
|
63
56
|
setStoreGroupBy(keys);
|
|
64
57
|
}, [setStoreGroupBy]);
|
|
65
|
-
const groupBy = useMemo(() => {
|
|
66
|
-
if (storeGroupBy !== undefined) {
|
|
67
|
-
if (typeof storeGroupBy === 'string') {
|
|
68
|
-
return [storeGroupBy];
|
|
69
|
-
}
|
|
70
|
-
return storeGroupBy;
|
|
71
|
-
}
|
|
72
|
-
return [FIELD_FUNCTION_NAME];
|
|
73
|
-
}, [storeGroupBy]);
|
|
74
58
|
const toggleGroupBy = useCallback((key) => {
|
|
75
59
|
groupBy.includes(key)
|
|
76
60
|
? setGroupBy(groupBy.filter(v => v !== key)) // remove
|
|
@@ -78,29 +62,19 @@ const GroupAndSortActionButtons = ({ navigateTo }) => {
|
|
|
78
62
|
}, [groupBy, setGroupBy]);
|
|
79
63
|
return (_jsxs(_Fragment, { children: [_jsx(GroupByDropdown, { groupBy: groupBy, toggleGroupBy: toggleGroupBy }), _jsx(SortBySelect, { compareMode: compareMode, sortBy: storeSortBy, setSortBy: setStoreSortBy })] }));
|
|
80
64
|
};
|
|
81
|
-
const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType,
|
|
65
|
+
const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, setActionButtons, error, width, isHalfScreen, mappings, }) {
|
|
82
66
|
const { onError, authenticationErrorMessage, isDarkMode } = useParcaContext();
|
|
83
67
|
const { compareMode } = useProfileViewContext();
|
|
84
68
|
const [isLoading, setIsLoading] = useState(true);
|
|
85
69
|
const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
86
70
|
const mappingsList = useMappingList(mappings);
|
|
87
|
-
const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState(
|
|
88
|
-
|
|
89
|
-
navigateTo,
|
|
90
|
-
});
|
|
91
|
-
const [invertStack = '', setInvertStack] = useURLState({
|
|
92
|
-
param: 'invert_call_stack',
|
|
93
|
-
navigateTo,
|
|
94
|
-
});
|
|
71
|
+
const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState('sort_by');
|
|
72
|
+
const [invertStack = '', setInvertStack] = useURLState('invert_call_stack');
|
|
95
73
|
const isInvert = invertStack === 'true';
|
|
96
74
|
// By default, we want delta profiles (CPU) to be relatively compared.
|
|
97
75
|
// For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
|
|
98
76
|
const compareAbsoluteDefault = profileType?.delta === false ? 'true' : 'false';
|
|
99
|
-
const [compareAbsolute = compareAbsoluteDefault, setCompareAbsolute] = useURLState(
|
|
100
|
-
param: 'compare_absolute',
|
|
101
|
-
navigateTo,
|
|
102
|
-
withURLUpdate: true,
|
|
103
|
-
});
|
|
77
|
+
const [compareAbsolute = compareAbsoluteDefault, setCompareAbsolute] = useURLState('compare_absolute');
|
|
104
78
|
const isCompareAbsolute = compareAbsolute === 'true';
|
|
105
79
|
const [totalFormatted, totalUnfilteredFormatted, isTrimmed, trimmedFormatted, trimmedPercentage, isFiltered, filteredPercentage,] = useMemo(() => {
|
|
106
80
|
if (graph === undefined && arrow === undefined) {
|
|
@@ -121,9 +95,8 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
121
95
|
];
|
|
122
96
|
}, [graph, arrow, filtered, total]);
|
|
123
97
|
useEffect(() => {
|
|
124
|
-
setActionButtons?.(_jsx("div", { className: "flex w-full justify-end gap-2 pb-2", children: _jsxs("div", { className: "ml-2 flex w-full flex-col items-start justify-between gap-2 md:flex-row md:items-end", children: [_jsx(GroupAndSortActionButtons, {
|
|
98
|
+
setActionButtons?.(_jsx("div", { className: "flex w-full justify-end gap-2 pb-2", children: _jsxs("div", { className: "ml-2 flex w-full flex-col items-start justify-between gap-2 md:flex-row md:items-end", children: [_jsx(GroupAndSortActionButtons, {}), isHalfScreen ? (_jsx(IconButton, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', toolTipText: isInvert ? 'Original Call Stack' : 'Invert Call Stack', onClick: () => setInvertStack(isInvert ? '' : 'true'), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setInvertStack(isInvert ? '' : 'true'), children: [isInvert ? 'Original Call Stack' : 'Invert Call Stack', _jsx(Icon, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', width: 20 })] })), _jsx(ShowHideLegendButton, { isHalfScreen: isHalfScreen }), compareMode && (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setCompareAbsolute(isCompareAbsolute ? '' : 'true'), children: [isCompareAbsolute ? 'Compare Relative' : 'Compare Absolute', _jsx(Icon, { icon: isCompareAbsolute ? 'fluent-mdl2:compare' : 'fluent-mdl2:compare-uneven', width: 20 })] })), isHalfScreen ? (_jsx(IconButton, { icon: "system-uicons:reset", disabled: curPath.length === 0, toolTipText: "Reset View", onClick: () => setNewCurPath([]), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, children: ["Reset View", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }))] }) }));
|
|
125
99
|
}, [
|
|
126
|
-
navigateTo,
|
|
127
100
|
isInvert,
|
|
128
101
|
setInvertStack,
|
|
129
102
|
arrow,
|
|
@@ -155,9 +128,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
155
128
|
if (total === 0n && !loading)
|
|
156
129
|
return _jsx("div", { className: "mx-auto text-center", children: "Profile has no samples" });
|
|
157
130
|
if (graph !== undefined)
|
|
158
|
-
return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType
|
|
131
|
+
return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType }));
|
|
159
132
|
if (arrow !== undefined)
|
|
160
|
-
return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType,
|
|
133
|
+
return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList }));
|
|
161
134
|
}, [
|
|
162
135
|
isLoading,
|
|
163
136
|
graph,
|
|
@@ -169,7 +142,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
169
142
|
curPath,
|
|
170
143
|
setNewCurPath,
|
|
171
144
|
profileType,
|
|
172
|
-
navigateTo,
|
|
173
145
|
storeSortBy,
|
|
174
146
|
isHalfScreen,
|
|
175
147
|
isDarkMode,
|
|
@@ -185,6 +157,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
185
157
|
if (isTrimmed) {
|
|
186
158
|
console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
|
|
187
159
|
}
|
|
188
|
-
return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, isColorStackLegendEnabled && (_jsx(ColorStackLegend, {
|
|
160
|
+
return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, isColorStackLegendEnabled && (_jsx(ColorStackLegend, { compareMode: compareMode, mappings: mappings, loading: isLoading })), _jsx("div", { className: "min-h-48", id: "h-icicle-graph", children: _jsx(_Fragment, { children: icicleGraph }) }), _jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] })] }, "icicle-graph-loaded") }));
|
|
189
161
|
};
|
|
190
162
|
export default ProfileIcicleGraph;
|
|
@@ -36,8 +36,7 @@ const getStepCountFromScreenWidth = (pixelsPerPoint) => {
|
|
|
36
36
|
};
|
|
37
37
|
export const useQueryRange = (client, queryExpression, start, end, sumBy, skip = false) => {
|
|
38
38
|
const metadata = useGrpcMetadata();
|
|
39
|
-
const
|
|
40
|
-
const [stepCountStr, setStepCount] = useURLState({ param: 'step_count', navigateTo });
|
|
39
|
+
const [stepCountStr, setStepCount] = useURLState('step_count');
|
|
41
40
|
const defaultStepCount = useMemo(() => {
|
|
42
41
|
return getStepCountFromScreenWidth(10);
|
|
43
42
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,6IAUlB,oBAAoB,KAAG,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,6IAUlB,oBAAoB,KAAG,GAAG,CAAC,OA6U7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
14
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
15
15
|
import Select from 'react-select';
|
|
16
16
|
import { Button, ButtonGroup, DateTimeRange, DateTimeRangePicker, IconButton, useGrpcMetadata, useParcaContext, } from '@parca/components';
|
|
17
17
|
import { CloseIcon } from '@parca/icons';
|
|
@@ -44,6 +44,7 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
|
|
|
44
44
|
const { loading: profileTypesLoading, data: profileTypesData, error, } = useProfileTypes(queryClient);
|
|
45
45
|
const { heightStyle } = useMetricsGraphDimensions(comparing);
|
|
46
46
|
const { viewComponent } = useParcaContext();
|
|
47
|
+
const sumByRef = useRef(null);
|
|
47
48
|
const [timeRangeSelection, setTimeRangeSelection] = useState(DateTimeRange.fromRangeKey(querySelection.timeSelection, querySelection.from, querySelection.to));
|
|
48
49
|
const [queryExpressionString, setQueryExpressionString] = useState(querySelection.expression);
|
|
49
50
|
const profileType = useMemo(() => {
|
|
@@ -171,7 +172,23 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
|
|
|
171
172
|
setUserSumBySelection(selectedOptions.map(option => option.value));
|
|
172
173
|
}, placeholder: "Labels...", styles: {
|
|
173
174
|
indicatorSeparator: () => ({ display: 'none' }),
|
|
174
|
-
}, isDisabled: !profileType.delta
|
|
175
|
+
}, isDisabled: !profileType.delta, ref: sumByRef, onKeyDown: e => {
|
|
176
|
+
const currentRef = sumByRef.current;
|
|
177
|
+
if (currentRef == null) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const inputRef = currentRef.inputRef;
|
|
181
|
+
if (inputRef == null) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (e.key === 'Enter' &&
|
|
185
|
+
inputRef.value === '' &&
|
|
186
|
+
currentRef.state.focusedOptionId === null // menu is not open
|
|
187
|
+
) {
|
|
188
|
+
setQueryExpression(true);
|
|
189
|
+
currentRef.blur();
|
|
190
|
+
}
|
|
191
|
+
} })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
|
|
175
192
|
e.preventDefault();
|
|
176
193
|
setQueryExpression(true);
|
|
177
194
|
}, id: "h-matcher-search-button", children: "Search" }) })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
declare const FilterByFunctionButton: ({ navigateTo, }: {
|
|
3
|
-
navigateTo: NavigateFunction | undefined;
|
|
4
|
-
}) => JSX.Element;
|
|
1
|
+
declare const FilterByFunctionButton: () => JSX.Element;
|
|
5
2
|
export default FilterByFunctionButton;
|
|
6
3
|
//# sourceMappingURL=FilterByFunctionButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterByFunctionButton.d.ts","sourceRoot":"","sources":["../../src/ProfileView/FilterByFunctionButton.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FilterByFunctionButton.d.ts","sourceRoot":"","sources":["../../src/ProfileView/FilterByFunctionButton.tsx"],"names":[],"mappings":"AAoBA,QAAA,MAAM,sBAAsB,QAAO,GAAG,CAAC,OAuCtC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -14,8 +14,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
14
14
|
import { useCallback, useMemo, useState } from 'react';
|
|
15
15
|
import { Icon } from '@iconify/react';
|
|
16
16
|
import { Input, useURLState } from '@parca/components';
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
|
|
18
|
+
const FilterByFunctionButton = () => {
|
|
19
|
+
const [highlightAfterFilteringEnabled] = useUserPreference(USER_PREFERENCES.HIGHTLIGHT_AFTER_FILTERING.key);
|
|
20
|
+
const [storeValue, setStoreValue] = useURLState('filter_by_function');
|
|
21
|
+
const [_, setSearchString] = useURLState('search_string');
|
|
19
22
|
const [localValue, setLocalValue] = useState(storeValue);
|
|
20
23
|
const isClearAction = useMemo(() => {
|
|
21
24
|
return localValue === storeValue && localValue != null && localValue !== '';
|
|
@@ -24,11 +27,17 @@ const FilterByFunctionButton = ({ navigateTo, }) => {
|
|
|
24
27
|
if (isClearAction) {
|
|
25
28
|
setLocalValue('');
|
|
26
29
|
setStoreValue('');
|
|
30
|
+
if (highlightAfterFilteringEnabled) {
|
|
31
|
+
setSearchString('');
|
|
32
|
+
}
|
|
27
33
|
}
|
|
28
34
|
else {
|
|
29
35
|
setStoreValue(localValue);
|
|
36
|
+
if (highlightAfterFilteringEnabled) {
|
|
37
|
+
setSearchString(localValue);
|
|
38
|
+
}
|
|
30
39
|
}
|
|
31
|
-
}, [localValue, isClearAction, setStoreValue]);
|
|
40
|
+
}, [localValue, isClearAction, setStoreValue, highlightAfterFilteringEnabled, setSearchString]);
|
|
32
41
|
return (_jsx(Input, { placeholder: "Filter by function", className: "text-sm", onAction: onAction, onChange: e => setLocalValue(e.target.value), value: localValue ?? '', onBlur: () => setLocalValue(storeValue), actionIcon: isClearAction ? _jsx(Icon, { icon: "ep:circle-close" }) : _jsx(Icon, { icon: "ep:arrow-right" }), id: "h-filter-by-function" }));
|
|
33
42
|
};
|
|
34
43
|
export default FilterByFunctionButton;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import type { NavigateFunction } from '@parca/utilities';
|
|
2
1
|
interface Props {
|
|
3
2
|
position: number;
|
|
4
3
|
defaultValue: string;
|
|
5
|
-
navigateTo?: NavigateFunction;
|
|
6
4
|
placeholderText?: string;
|
|
7
5
|
primary?: boolean;
|
|
8
6
|
addView?: boolean;
|
|
@@ -10,6 +8,6 @@ interface Props {
|
|
|
10
8
|
icon?: JSX.Element;
|
|
11
9
|
id?: string;
|
|
12
10
|
}
|
|
13
|
-
declare const ViewSelector: ({ defaultValue,
|
|
11
|
+
declare const ViewSelector: ({ defaultValue, position, placeholderText, primary, addView, disabled, icon, id, }: Props) => JSX.Element;
|
|
14
12
|
export default ViewSelector;
|
|
15
13
|
//# sourceMappingURL=ViewSelector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewSelector.d.ts","sourceRoot":"","sources":["../../src/ProfileView/ViewSelector.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ViewSelector.d.ts","sourceRoot":"","sources":["../../src/ProfileView/ViewSelector.tsx"],"names":[],"mappings":"AAgBA,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,YAAY,uFASf,KAAK,KAAG,GAAG,CAAC,OAoFd,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -13,11 +13,10 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
import { Select, useParcaContext, useURLState } from '@parca/components';
|
|
15
15
|
import { useUIFeatureFlag } from '@parca/hooks';
|
|
16
|
-
const ViewSelector = ({ defaultValue,
|
|
16
|
+
const ViewSelector = ({ defaultValue, position, placeholderText, primary = false, addView = false, disabled = false, icon, id, }) => {
|
|
17
17
|
const [callgraphEnabled] = useUIFeatureFlag('callgraph');
|
|
18
|
-
const [dashboardItems = ['icicle'], setDashboardItems] = useURLState({
|
|
19
|
-
|
|
20
|
-
navigateTo,
|
|
18
|
+
const [dashboardItems = ['icicle'], setDashboardItems] = useURLState('dashboard_items', {
|
|
19
|
+
alwaysReturnArray: true,
|
|
21
20
|
});
|
|
22
21
|
const { enableSourcesView } = useParcaContext();
|
|
23
22
|
const allItems = [
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
|
|
3
|
-
import type { NavigateFunction } from '@parca/utilities';
|
|
4
3
|
interface Props {
|
|
5
4
|
dashboardItem: string;
|
|
6
5
|
index: number;
|
|
7
6
|
isMultiPanelView: boolean;
|
|
8
7
|
handleClosePanel: (dashboardItem: string) => void;
|
|
9
|
-
navigateTo: NavigateFunction | undefined;
|
|
10
8
|
dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
|
|
11
9
|
getDashboardItemByType: (props: {
|
|
12
10
|
type: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VisualizationPanel.d.ts","sourceRoot":"","sources":["../../src/ProfileView/VisualizationPanel.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAItC,OAAO,KAAK,EAAC,gCAAgC,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"VisualizationPanel.d.ts","sourceRoot":"","sources":["../../src/ProfileView/VisualizationPanel.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAItC,OAAO,KAAK,EAAC,gCAAgC,EAAC,MAAM,qBAAqB,CAAC;AAO1E,UAAU,KAAK;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,gCAAgC,GAAG,IAAI,GAAG,SAAS,CAAC;IACrE,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAC9B,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,OAAO,CAAC;QACtB,gBAAgB,EAAE,CAAC,aAAa,EAAE,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;KACxD,KAAK,GAAG,CAAC,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,kBAAkB,mCAyD7B,CAAC"}
|
|
@@ -17,10 +17,10 @@ import cx from 'classnames';
|
|
|
17
17
|
import { IconButton, useParcaContext } from '@parca/components';
|
|
18
18
|
import { CloseIcon } from '@parca/icons';
|
|
19
19
|
import ViewSelector from './ViewSelector';
|
|
20
|
-
export const VisualizationPanel = React.memo(function VisualizationPanel({ dashboardItem, index, isMultiPanelView, handleClosePanel,
|
|
20
|
+
export const VisualizationPanel = React.memo(function VisualizationPanel({ dashboardItem, index, isMultiPanelView, handleClosePanel, dragHandleProps, getDashboardItemByType, }) {
|
|
21
21
|
const [actionButtons, setActionButtons] = useState(_jsx(_Fragment, {}));
|
|
22
22
|
const { flamegraphHint } = useParcaContext();
|
|
23
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex w-full items-center justify-end gap-2 pb-2 min-h-[78px]", children: [_jsxs("div", { className: cx('flex w-full justify-between flex-col-reverse md:flex-row', isMultiPanelView && dashboardItem === 'icicle' ? 'items-end gap-x-2' : 'items-end'), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: cx(isMultiPanelView ? '' : 'hidden', 'flex items-center'), ...dragHandleProps, children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) }), _jsx("div", { className: "flex gap-2", children: actionButtons })] }), _jsxs("div", { className: cx('flex flex-row items-center gap-4', isMultiPanelView && dashboardItem === 'icicle' && 'pb-[10px]'), children: [_jsx(ViewSelector, { id: "h-switch-viz", defaultValue: dashboardItem,
|
|
23
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex w-full items-center justify-end gap-2 pb-2 min-h-[78px]", children: [_jsxs("div", { className: cx('flex w-full justify-between flex-col-reverse md:flex-row', isMultiPanelView && dashboardItem === 'icicle' ? 'items-end gap-x-2' : 'items-end'), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: cx(isMultiPanelView ? '' : 'hidden', 'flex items-center'), ...dragHandleProps, children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) }), _jsx("div", { className: "flex gap-2", children: actionButtons })] }), _jsxs("div", { className: cx('flex flex-row items-center gap-4', isMultiPanelView && dashboardItem === 'icicle' && 'pb-[10px]'), children: [_jsx(ViewSelector, { id: "h-switch-viz", defaultValue: dashboardItem, position: index }), dashboardItem === 'icicle' && flamegraphHint != null ? (_jsx("div", { className: "px-2", children: flamegraphHint })) : null] })] }), isMultiPanelView && (_jsx(IconButton, { className: "py-0", onClick: () => handleClosePanel(dashboardItem), icon: _jsx(CloseIcon, {}) }))] }), getDashboardItemByType({
|
|
24
24
|
type: dashboardItem,
|
|
25
25
|
isHalfScreen: isMultiPanelView,
|
|
26
26
|
setActionButtons,
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { Callgraph as CallgraphType, Flamegraph, FlamegraphArrow, QueryServiceClient, Source, TableArrow, Top } from '@parca/client';
|
|
2
2
|
import { ProfileSource } from '../ProfileSource';
|
|
3
|
-
type NavigateFunction = (path: string, queryParams: any, options?: {
|
|
4
|
-
replace?: boolean;
|
|
5
|
-
}) => void;
|
|
6
3
|
export interface FlamegraphData {
|
|
7
4
|
loading: boolean;
|
|
8
5
|
data?: Flamegraph;
|
|
@@ -43,11 +40,10 @@ export interface ProfileViewProps {
|
|
|
43
40
|
sourceData?: SourceData;
|
|
44
41
|
profileSource?: ProfileSource;
|
|
45
42
|
queryClient?: QueryServiceClient;
|
|
46
|
-
navigateTo?: NavigateFunction;
|
|
47
43
|
compare?: boolean;
|
|
48
44
|
onDownloadPProf: () => void;
|
|
49
45
|
pprofDownloading?: boolean;
|
|
50
46
|
}
|
|
51
|
-
export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient,
|
|
47
|
+
export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, }: ProfileViewProps) => JSX.Element;
|
|
52
48
|
export {};
|
|
53
49
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA2BA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACV,GAAG,EACJ,MAAM,eAAe,CAAC;AAgBvB,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAS/C,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA2BA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACV,GAAG,EACJ,MAAM,eAAe,CAAC;AAgBvB,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAS/C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAWD,eAAO,MAAM,WAAW,0JAYrB,gBAAgB,KAAG,GAAG,CAAC,OAoUzB,CAAC"}
|
|
@@ -12,7 +12,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
12
12
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
|
-
import { Profiler, useEffect,
|
|
15
|
+
import { Profiler, useEffect, useState } from 'react';
|
|
16
16
|
import { Icon } from '@iconify/react';
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
import { scaleLinear } from 'd3';
|
|
@@ -26,7 +26,7 @@ import { Callgraph } from '../';
|
|
|
26
26
|
import { jsonToDot } from '../Callgraph/utils';
|
|
27
27
|
import ProfileIcicleGraph from '../ProfileIcicleGraph';
|
|
28
28
|
import { SourceView } from '../SourceView';
|
|
29
|
-
import Table from '../Table';
|
|
29
|
+
import { Table } from '../Table';
|
|
30
30
|
import ProfileShareButton from '../components/ProfileShareButton';
|
|
31
31
|
import FilterByFunctionButton from './FilterByFunctionButton';
|
|
32
32
|
import { ProfileViewContextProvider } from './ProfileViewContext';
|
|
@@ -38,23 +38,16 @@ function arrayEquals(a, b) {
|
|
|
38
38
|
a.length === b.length &&
|
|
39
39
|
a.every((val, index) => val === b[index]));
|
|
40
40
|
}
|
|
41
|
-
export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient,
|
|
41
|
+
export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, }) => {
|
|
42
42
|
const { timezone } = useParcaContext();
|
|
43
43
|
const { ref, dimensions } = useContainerDimensions();
|
|
44
44
|
const [curPath, setCurPath] = useState([]);
|
|
45
|
-
const [
|
|
46
|
-
|
|
47
|
-
navigateTo,
|
|
45
|
+
const [dashboardItems, setDashboardItems] = useURLState('dashboard_items', {
|
|
46
|
+
alwaysReturnArray: true,
|
|
48
47
|
});
|
|
49
48
|
const [graphvizLoaded, setGraphvizLoaded] = useState(false);
|
|
50
49
|
const [callgraphSVG, setCallgraphSVG] = useState(undefined);
|
|
51
|
-
const [currentSearchString] = useURLState(
|
|
52
|
-
const dashboardItems = useMemo(() => {
|
|
53
|
-
if (rawDashboardItems !== undefined) {
|
|
54
|
-
return rawDashboardItems;
|
|
55
|
-
}
|
|
56
|
-
return ['icicle'];
|
|
57
|
-
}, [rawDashboardItems]);
|
|
50
|
+
const [currentSearchString, setSearchString] = useURLState('search_string');
|
|
58
51
|
const isDarkMode = useAppSelector(selectDarkMode);
|
|
59
52
|
const isMultiPanelView = dashboardItems.length > 1;
|
|
60
53
|
const { perf, profileViewExternalMainActions, profileViewExternalSubActions } = useParcaContext();
|
|
@@ -107,7 +100,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
|
|
|
107
100
|
return (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
|
|
108
101
|
id: 'icicleGraph',
|
|
109
102
|
onRender: perf?.onRender,
|
|
110
|
-
}, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, arrow: flamegraphData?.arrow, graph: flamegraphData?.data, total: total, filtered: filtered, profileType: profileSource?.ProfileType(),
|
|
103
|
+
}, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, arrow: flamegraphData?.arrow, graph: flamegraphData?.data, total: total, filtered: filtered, profileType: profileSource?.ProfileType(), loading: flamegraphData.loading, setActionButtons: setActionButtons, error: flamegraphData.error, isHalfScreen: isHalfScreen, width: dimensions?.width !== undefined
|
|
111
104
|
? isHalfScreen
|
|
112
105
|
? (dimensions.width - 40) / 2
|
|
113
106
|
: dimensions.width - 16
|
|
@@ -119,7 +112,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
|
|
|
119
112
|
dimensions?.width !== undefined ? (_jsx(Callgraph, { data: callgraphData.data, svgString: callgraphSVG, profileType: profileSource?.ProfileType(), width: isHalfScreen ? dimensions?.width / 2 : dimensions?.width })) : (_jsx(_Fragment, {}));
|
|
120
113
|
}
|
|
121
114
|
case 'table': {
|
|
122
|
-
return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(),
|
|
115
|
+
return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), setActionButtons: setActionButtons, currentSearchString: currentSearchString, setSearchString: setSearchString, isHalfScreen: isHalfScreen })) : (_jsx(_Fragment, {}));
|
|
123
116
|
}
|
|
124
117
|
case 'source': {
|
|
125
118
|
return sourceData != null ? (_jsx(SourceView, { loading: sourceData.loading, data: sourceData.data, total: total, filtered: filtered, setActionButtons: setActionButtons })) : (_jsx(_Fragment, {}));
|
|
@@ -157,13 +150,13 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
|
|
|
157
150
|
'items-center': hasProfileSource,
|
|
158
151
|
}), children: [_jsxs("div", { children: [hasProfileSource && (_jsxs("div", { className: "max-w-[300px]", children: [_jsx("div", { className: "text-sm font-medium capitalize", children: headerParts.length > 0 ? headerParts[0].replace(/"/g, '') : '' }), _jsx("div", { className: "text-xs", children: headerParts.length > 1
|
|
159
152
|
? headerParts[headerParts.length - 1].replace(/"/g, '')
|
|
160
|
-
: '' })] })), profileViewExternalMainActions != null ? profileViewExternalMainActions : null] }), _jsxs("div", { className: "lg:flex flex-wrap items-center gap-2 md:justify-end hidden", children: [_jsx(FilterByFunctionButton, {
|
|
153
|
+
: '' })] })), profileViewExternalMainActions != null ? profileViewExternalMainActions : null] }), _jsxs("div", { className: "lg:flex flex-wrap items-center gap-2 md:justify-end hidden", children: [_jsx(FilterByFunctionButton, {}), profileViewExternalSubActions != null ? profileViewExternalSubActions : null, _jsx(UserPreferences, { customButton: _jsxs(Button, { className: "gap-2", variant: "neutral", id: "h-viz-preferences", children: ["Preferences", _jsx(Icon, { icon: "pajamas:preferences", width: 20 })] }) }), profileSource !== undefined && queryClient !== undefined ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient })) : null, _jsxs(Button, { className: "gap-2", variant: "neutral", onClick: e => {
|
|
161
154
|
e.preventDefault();
|
|
162
155
|
onDownloadPProf();
|
|
163
|
-
}, disabled: pprofDownloading, id: "h-download-pprof", children: [pprofDownloading != null && pprofDownloading ? 'Downloading...' : 'Download pprof', _jsx(Icon, { icon: "material-symbols:download", width: 20 })] }), _jsx(ViewSelector, { defaultValue: "",
|
|
156
|
+
}, disabled: pprofDownloading, id: "h-download-pprof", children: [pprofDownloading != null && pprofDownloading ? 'Downloading...' : 'Download pprof', _jsx(Icon, { icon: "material-symbols:download", width: 20 })] }), _jsx(ViewSelector, { defaultValue: "", position: -1, placeholderText: "Add panel", icon: _jsx(Icon, { icon: "material-symbols:add", width: 20 }), addView: true, disabled: isMultiPanelView || dashboardItems.length < 1, id: "h-add-panel" })] })] }), _jsx("div", { className: "w-full", ref: ref, children: _jsx(DragDropContext, { onDragEnd: onDragEnd, children: _jsx(Droppable, { droppableId: "droppable", direction: "horizontal", children: provided => (_jsx("div", { ref: provided.innerRef, className: cx('grid w-full gap-2', isMultiPanelView ? 'grid-cols-2' : 'grid-cols-1'), ...provided.droppableProps, children: dashboardItems.map((dashboardItem, index) => {
|
|
164
157
|
return (_jsx(Draggable, { draggableId: dashboardItem, index: index, isDragDisabled: !isMultiPanelView, children: (provided, snapshot) => (_createElement("div", { ref: provided.innerRef, ...provided.draggableProps, key: dashboardItem, className: cx('w-full rounded p-2 shadow dark:border dark:border-gray-700 dark:bg-gray-700 min-h-96', snapshot.isDragging
|
|
165
158
|
? 'bg-gray-200 dark:bg-gray-500'
|
|
166
159
|
: 'bg-white dark:bg-gray-700') },
|
|
167
|
-
_jsx(VisualizationPanel, { handleClosePanel: handleClosePanel, isMultiPanelView: isMultiPanelView, dashboardItem: dashboardItem, getDashboardItemByType: getDashboardItemByType, dragHandleProps: provided.dragHandleProps,
|
|
160
|
+
_jsx(VisualizationPanel, { handleClosePanel: handleClosePanel, isMultiPanelView: isMultiPanelView, dashboardItem: dashboardItem, getDashboardItemByType: getDashboardItemByType, dragHandleProps: provided.dragHandleProps, index: index }))) }, dashboardItem));
|
|
168
161
|
}) })) }) }) })] }) }));
|
|
169
162
|
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { QueryServiceClient } from '@parca/client';
|
|
2
|
-
import { type NavigateFunction } from '@parca/utilities';
|
|
3
2
|
import { ProfileSource } from './ProfileSource';
|
|
4
3
|
interface ProfileViewWithDataProps {
|
|
5
4
|
queryClient: QueryServiceClient;
|
|
6
5
|
profileSource: ProfileSource;
|
|
7
|
-
navigateTo?: NavigateFunction;
|
|
8
6
|
compare?: boolean;
|
|
9
7
|
}
|
|
10
|
-
export declare const ProfileViewWithData: ({ queryClient, profileSource,
|
|
8
|
+
export declare const ProfileViewWithData: ({ queryClient, profileSource, }: ProfileViewWithDataProps) => JSX.Element;
|
|
11
9
|
export default ProfileViewWithData;
|
|
12
10
|
//# sourceMappingURL=ProfileViewWithData.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAK1E,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAK9C,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB,oCAG7B,wBAAwB,KAAG,GAAG,CAAC,OA+MjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -19,15 +19,20 @@ import { FIELD_FUNCTION_NAME } from './ProfileIcicleGraph/IcicleGraphArrow';
|
|
|
19
19
|
import { ProfileView } from './ProfileView';
|
|
20
20
|
import { useQuery } from './useQuery';
|
|
21
21
|
import { downloadPprof } from './utils';
|
|
22
|
-
export const ProfileViewWithData = ({ queryClient, profileSource,
|
|
22
|
+
export const ProfileViewWithData = ({ queryClient, profileSource, }) => {
|
|
23
23
|
const metadata = useGrpcMetadata();
|
|
24
|
-
const [dashboardItems
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const [
|
|
28
|
-
const [
|
|
24
|
+
const [dashboardItems] = useURLState('dashboard_items', {
|
|
25
|
+
alwaysReturnArray: true,
|
|
26
|
+
});
|
|
27
|
+
const [sourceBuildID] = useURLState('source_buildid');
|
|
28
|
+
const [sourceFilename] = useURLState('source_filename');
|
|
29
|
+
const [groupBy] = useURLState('group_by', {
|
|
30
|
+
defaultValue: [FIELD_FUNCTION_NAME],
|
|
31
|
+
alwaysReturnArray: true,
|
|
32
|
+
});
|
|
33
|
+
const [invertStack] = useURLState('invert_call_stack');
|
|
29
34
|
const invertCallStack = invertStack === 'true';
|
|
30
|
-
const [binaryFrameFilterStr] = useURLState(
|
|
35
|
+
const [binaryFrameFilterStr] = useURLState('binary_frame_filter');
|
|
31
36
|
const binaryFrameFilter = typeof binaryFrameFilterStr === 'string'
|
|
32
37
|
? binaryFrameFilterStr.split(',')
|
|
33
38
|
: binaryFrameFilterStr;
|
|
@@ -40,19 +45,17 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
|
|
|
40
45
|
width = width - 12 - 16 - 12;
|
|
41
46
|
return (1 / width) * 100;
|
|
42
47
|
}, []);
|
|
43
|
-
// make sure we get a string[]
|
|
44
|
-
const groupByParam = typeof groupBy === 'string' ? [groupBy] : groupBy;
|
|
45
48
|
const { isLoading: flamegraphLoading, response: flamegraphResponse, error: flamegraphError, } = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_ARROW, {
|
|
46
49
|
skip: !dashboardItems.includes('icicle'),
|
|
47
50
|
nodeTrimThreshold,
|
|
48
|
-
groupBy
|
|
51
|
+
groupBy,
|
|
49
52
|
invertCallStack,
|
|
50
53
|
binaryFrameFilter,
|
|
51
54
|
});
|
|
52
55
|
const { isLoading: profilemetadataLoading, response: profilemetadataResponse } = useQuery(queryClient, profileSource, QueryRequest_ReportType.PROFILE_METADATA, {
|
|
53
56
|
skip: !dashboardItems.includes('icicle'),
|
|
54
57
|
nodeTrimThreshold,
|
|
55
|
-
groupBy
|
|
58
|
+
groupBy,
|
|
56
59
|
invertCallStack,
|
|
57
60
|
binaryFrameFilter: undefined,
|
|
58
61
|
});
|
|
@@ -164,6 +167,6 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
|
|
|
164
167
|
? sourceResponse?.report?.source
|
|
165
168
|
: undefined,
|
|
166
169
|
error: sourceError,
|
|
167
|
-
}, profileSource: profileSource, queryClient: queryClient,
|
|
170
|
+
}, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: () => void downloadPProfClick(), pprofDownloading: pprofDownloading }));
|
|
168
171
|
};
|
|
169
172
|
export default ProfileViewWithData;
|
package/dist/SourceView/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import { Highlighter, profileAwareRenderer } from './Highlighter';
|
|
|
22
22
|
import useLineRange from './useSelectedLineRange';
|
|
23
23
|
const MENU_ID = 'source-view-context-menu';
|
|
24
24
|
export const SourceView = React.memo(function SourceView({ data, loading, total, filtered, setActionButtons, }) {
|
|
25
|
-
const [sourceFileName] = useURLState(
|
|
25
|
+
const [sourceFileName] = useURLState('source_filename');
|
|
26
26
|
const { isDarkMode, sourceViewContextMenuItems = [] } = useParcaContext();
|
|
27
27
|
const sourceCode = useMemo(() => {
|
|
28
28
|
if (data === undefined) {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { useMemo } from 'react';
|
|
14
14
|
import { useURLState } from '@parca/components';
|
|
15
15
|
const useLineRange = () => {
|
|
16
|
-
const [sourceLine, setSourceLine] = useURLState(
|
|
16
|
+
const [sourceLine, setSourceLine] = useURLState('source_line');
|
|
17
17
|
const [startLine, endLine] = useMemo(() => {
|
|
18
18
|
if (sourceLine == null) {
|
|
19
19
|
return [-1, -1];
|
package/dist/Table/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Vector } from 'apache-arrow';
|
|
3
3
|
import { ProfileType } from '@parca/parser';
|
|
4
|
-
import { type NavigateFunction } from '@parca/utilities';
|
|
5
4
|
export interface DataRow {
|
|
6
5
|
id: number;
|
|
7
6
|
name: string;
|
|
@@ -30,9 +29,9 @@ interface TableProps {
|
|
|
30
29
|
total: bigint;
|
|
31
30
|
filtered: bigint;
|
|
32
31
|
profileType?: ProfileType;
|
|
33
|
-
navigateTo?: NavigateFunction;
|
|
34
32
|
loading: boolean;
|
|
35
33
|
currentSearchString?: string;
|
|
34
|
+
setSearchString?: (searchString: string) => void;
|
|
36
35
|
setActionButtons?: (buttons: React.JSX.Element) => void;
|
|
37
36
|
isHalfScreen: boolean;
|
|
38
37
|
unit?: string;
|