@parca/profile 0.19.52 → 0.19.54
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 +10 -0
- package/dist/MatchersInput/index.js +3 -3
- package/dist/MetricsGraph/MetricsContextMenu/index.js +2 -2
- package/dist/MetricsGraph/MetricsTooltip/index.js +2 -2
- package/dist/MetricsGraph/index.js +2 -2
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +2 -2
- package/dist/ProfileExplorer/index.js +3 -3
- package/dist/ProfileFlameGraph/index.js +2 -2
- package/dist/ProfileMetricsGraph/index.js +3 -3
- package/dist/ProfileSelector/QueryControls.js +6 -6
- package/dist/ProfileTypeSelector/index.js +2 -2
- package/dist/ProfileView/components/DashboardItems/index.d.ts +0 -2
- package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
- package/dist/ProfileView/components/DiffLegend.js +2 -2
- package/dist/ProfileView/components/GroupByLabelsDropdown/index.js +3 -3
- package/dist/ProfileView/components/ProfileFilters/index.js +6 -6
- package/dist/ProfileView/components/ProfileFilters/useProfileFilters.d.ts.map +1 -1
- package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +10 -4
- package/dist/ProfileView/components/Toolbars/index.js +2 -2
- package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts +2 -0
- package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -0
- package/dist/ProfileView/hooks/{useResetStateOnNewSearch.js → useResetFlameGraphState.js} +1 -1
- package/dist/ProfileView/hooks/useVisualizationState.d.ts +0 -2
- package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useVisualizationState.js +5 -5
- package/dist/ProfileView/index.d.ts.map +1 -1
- package/dist/ProfileView/index.js +1 -3
- package/dist/ProfileViewWithData.js +1 -1
- package/dist/SimpleMatchers/index.js +3 -3
- package/dist/ViewMatchers/index.js +2 -2
- package/package.json +4 -4
- package/src/MatchersInput/index.tsx +3 -3
- package/src/MetricsGraph/MetricsContextMenu/index.tsx +2 -2
- package/src/MetricsGraph/MetricsTooltip/index.tsx +2 -2
- package/src/MetricsGraph/index.tsx +2 -2
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +11 -5
- package/src/ProfileExplorer/index.tsx +3 -3
- package/src/ProfileFlameGraph/index.tsx +2 -2
- package/src/ProfileMetricsGraph/index.tsx +4 -4
- package/src/ProfileSelector/QueryControls.tsx +13 -13
- package/src/ProfileTypeSelector/index.tsx +2 -2
- package/src/ProfileView/components/DashboardItems/index.tsx +0 -2
- package/src/ProfileView/components/DiffLegend.tsx +2 -2
- package/src/ProfileView/components/GroupByLabelsDropdown/index.tsx +4 -4
- package/src/ProfileView/components/ProfileFilters/index.tsx +10 -10
- package/src/ProfileView/components/ProfileFilters/useProfileFilters.ts +10 -4
- package/src/ProfileView/components/Toolbars/index.tsx +2 -2
- package/src/ProfileView/hooks/{useResetStateOnNewSearch.ts → useResetFlameGraphState.ts} +1 -1
- package/src/ProfileView/hooks/useVisualizationState.ts +6 -7
- package/src/ProfileView/index.tsx +0 -4
- package/src/ProfileViewWithData.tsx +1 -1
- package/src/SimpleMatchers/index.tsx +9 -9
- package/src/ViewMatchers/index.tsx +2 -2
- package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts +0 -2
- package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.19.54](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.53...@parca/profile@0.19.54) (2025-09-16)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.19.53](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.52...@parca/profile@0.19.53) (2025-09-15)
|
|
11
|
+
|
|
12
|
+
## 0.24.2 (2025-09-10)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @parca/profile
|
|
15
|
+
|
|
6
16
|
## 0.19.52 (2025-09-15)
|
|
7
17
|
|
|
8
18
|
## 0.24.2 (2025-09-10)
|
|
@@ -17,7 +17,7 @@ import cx from 'classnames';
|
|
|
17
17
|
import TextareaAutosize from 'react-textarea-autosize';
|
|
18
18
|
import { useGrpcMetadata } from '@parca/components';
|
|
19
19
|
import { Query } from '@parca/parser';
|
|
20
|
-
import { testId } from '@parca/test-utils';
|
|
20
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
21
21
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
22
22
|
import { LabelsProvider, useLabels } from '../contexts/MatchersInputLabelsContext';
|
|
23
23
|
import useGrpcQuery from '../useGrpcQuery';
|
|
@@ -194,9 +194,9 @@ const MatchersInput = ({ setMatchersString, runQuery, currentQuery, }) => {
|
|
|
194
194
|
setFocusedInput(false);
|
|
195
195
|
};
|
|
196
196
|
const profileSelected = currentQuery.profileName() === '';
|
|
197
|
-
return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", ...testId(
|
|
197
|
+
return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", ...testId(TEST_IDS.MATCHERS_INPUT_CONTAINER), children: [_jsx(TextareaAutosize, { ref: inputRef, className: cx('block h-[38px] w-full flex-1 rounded-md border bg-white px-2 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900', profileSelected && 'cursor-not-allowed'), placeholder: profileSelected
|
|
198
198
|
? 'Select a profile first to enter a filter...'
|
|
199
|
-
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId(
|
|
199
|
+
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId(TEST_IDS.MATCHERS_TEXTAREA), onFocus: focus, disabled: profileSelected, title: profileSelected
|
|
200
200
|
? 'Select a profile first to enter a filter...'
|
|
201
201
|
: 'filter profiles... eg. node="test"', id: "matchers-input" }), _jsx(SuggestionsList, { isLabelNamesLoading: isLabelNamesLoading, suggestions: suggestionSections, applySuggestion: applySuggestion, inputRef: inputRef.current, runQuery: runQuery, focusedInput: focusedInput, isLabelValuesLoading: isLabelValuesLoading && lastCompleted.type === 'literal', shouldTrimPrefix: shouldHandlePrefixes })] }));
|
|
202
202
|
};
|
|
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
import { Icon } from '@iconify/react';
|
|
15
15
|
import { Item, Menu, Submenu } from 'react-contexify';
|
|
16
16
|
import { useParcaContext } from '@parca/components';
|
|
17
|
-
import { testId } from '@parca/test-utils';
|
|
17
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
18
18
|
const MetricsContextMenu = ({ menuId, closestPoint, series, trackVisibility, menuItems, }) => {
|
|
19
19
|
const { isDarkMode } = useParcaContext();
|
|
20
20
|
const renderMenuItem = (item) => {
|
|
@@ -32,6 +32,6 @@ const MetricsContextMenu = ({ menuId, closestPoint, series, trackVisibility, men
|
|
|
32
32
|
return (_jsx(Item, { id: menuItem.id, onClick: () => menuItem.onClick(closestPoint, series), disabled: menuItem.disabled?.(closestPoint, series) ?? false, children: _jsxs("div", { className: "flex w-full items-center gap-2", children: [menuItem.icon != null && menuItem.icon !== '' && _jsx(Icon, { icon: menuItem.icon }), _jsx("div", { children: menuItem.label })] }) }, menuItem.id));
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
return (_jsx(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', ...testId(
|
|
35
|
+
return (_jsx(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', ...testId(TEST_IDS.METRICS_GRAPH_CONTEXT_MENU), children: menuItems.map(renderMenuItem) }));
|
|
36
36
|
};
|
|
37
37
|
export default MetricsContextMenu;
|
|
@@ -13,7 +13,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
import { useEffect, useMemo, useState } from 'react';
|
|
15
15
|
import { usePopper } from 'react-popper';
|
|
16
|
-
import { testId } from '@parca/test-utils';
|
|
16
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
17
17
|
const virtualElement = {
|
|
18
18
|
getBoundingClientRect: () => {
|
|
19
19
|
const emptyRect = {
|
|
@@ -87,6 +87,6 @@ const MetricsTooltip = ({ x, y, contextElement, content }) => {
|
|
|
87
87
|
if (content == null) {
|
|
88
88
|
return _jsx(_Fragment, {});
|
|
89
89
|
}
|
|
90
|
-
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, ...testId(
|
|
90
|
+
return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, ...testId(TEST_IDS.METRICS_GRAPH_TOOLTIP), className: "z-50", children: _jsx("div", { className: "flex max-w-lg", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "border border-gray-300 bg-gray-50 dark:border-gray-500 dark:bg-gray-900 rounded-lg shadow-lg px-3 py-2", children: content }) }) }) }));
|
|
91
91
|
};
|
|
92
92
|
export default MetricsTooltip;
|
|
@@ -17,7 +17,7 @@ import { pointer } from 'd3-selection';
|
|
|
17
17
|
import throttle from 'lodash.throttle';
|
|
18
18
|
import { useContextMenu } from 'react-contexify';
|
|
19
19
|
import { DateTimeRange, useParcaContext } from '@parca/components';
|
|
20
|
-
import { testId } from '@parca/test-utils';
|
|
20
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
21
21
|
import { formatDate, formatForTimespan, getPrecision, valueFormatter } from '@parca/utilities';
|
|
22
22
|
import MetricsCircle from '../MetricsCircle';
|
|
23
23
|
import MetricsSeries from '../MetricsSeries';
|
|
@@ -26,7 +26,7 @@ import MetricsInfoPanel from './MetricsInfoPanel';
|
|
|
26
26
|
import MetricsTooltip from './MetricsTooltip';
|
|
27
27
|
const MetricsGraph = ({ data, from, to, onSampleClick, setTimeRange, yAxisLabel, yAxisUnit, width = 0, height = 0, margin = 0, selectedPoint, contextMenuItems, renderTooltipContent, }) => {
|
|
28
28
|
const [isInfoPanelOpen, setIsInfoPanelOpen] = useState(false);
|
|
29
|
-
return (_jsxs("div", { className: "relative", ...testId(
|
|
29
|
+
return (_jsxs("div", { className: "relative", ...testId(TEST_IDS.METRICS_GRAPH), onClick: () => isInfoPanelOpen && setIsInfoPanelOpen(false), children: [_jsx("div", { className: "absolute right-0 top-0", children: _jsx(MetricsInfoPanel, { isInfoPanelOpen: isInfoPanelOpen, onInfoIconClick: () => setIsInfoPanelOpen(true) }) }), _jsx(RawMetricsGraph, { data: data, from: from, to: to, onSampleClick: onSampleClick, setTimeRange: setTimeRange, yAxisLabel: yAxisLabel, yAxisUnit: yAxisUnit, width: width, height: height, margin: margin, selectedPoint: selectedPoint, contextMenuItems: contextMenuItems, renderTooltipContent: renderTooltipContent })] }));
|
|
30
30
|
};
|
|
31
31
|
export default MetricsGraph;
|
|
32
32
|
export const parseValue = (value) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,4IAY7B,2BAA2B,KAAG,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,4IAY7B,2BAA2B,KAAG,GAAG,CAAC,OA+EpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
import { useState } from 'react';
|
|
15
15
|
import { useURLState } from '@parca/components';
|
|
16
16
|
import { Query } from '@parca/parser';
|
|
17
|
-
import { testId } from '@parca/test-utils';
|
|
17
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
18
18
|
import { ProfileDiffSource, ProfileViewWithData } from '..';
|
|
19
19
|
import ProfileSelector from '../ProfileSelector';
|
|
20
20
|
const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profileB, selectQueryA, selectQueryB, selectProfileA, selectProfileB, closeProfile, navigateTo, }) => {
|
|
@@ -26,6 +26,6 @@ const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profile
|
|
|
26
26
|
closeProfile('B');
|
|
27
27
|
};
|
|
28
28
|
const [compareAbsolute] = useURLState('compare_absolute');
|
|
29
|
-
return (_jsxs("div", { ...testId(
|
|
29
|
+
return (_jsxs("div", { ...testId(TEST_IDS.COMPARE_CONTAINER), children: [_jsxs("div", { className: "flex justify-between gap-2 relative mb-2", children: [_jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId(TEST_IDS.COMPARE_SIDE_A), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo, suffix: "_a", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) }), _jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId(TEST_IDS.COMPARE_SIDE_B), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryB, profileSelection: profileB, selectProfile: selectProfileB, selectQuery: selectQueryB, closeProfile: closeProfileB, enforcedProfileName: Query.parse(queryA.expression).profileName(), comparing: true, navigateTo: navigateTo, suffix: "_b", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { ...testId(TEST_IDS.COMPARE_PROFILE_VIEW), children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource(), compareAbsolute === 'true') }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
|
|
30
30
|
};
|
|
31
31
|
export default ProfileExplorerCompare;
|
|
@@ -19,7 +19,7 @@ import { createStore } from '@parca/store';
|
|
|
19
19
|
import { capitalizeOnlyFirstLetter, safeDecode } from '@parca/utilities';
|
|
20
20
|
import { ProfileSelectionFromParams, SuffixParams } from '..';
|
|
21
21
|
import { useProfileTypes } from '../ProfileSelector';
|
|
22
|
-
import {
|
|
22
|
+
import { useResetFlameGraphState } from '../ProfileView/hooks/useResetFlameGraphState';
|
|
23
23
|
import { useResetStateOnProfileTypeChange } from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
|
|
24
24
|
import { sumByToParam, useSumByFromParams } from '../useSumBy';
|
|
25
25
|
import ProfileExplorerCompare from './ProfileExplorerCompare';
|
|
@@ -89,7 +89,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
|
|
|
89
89
|
const [profileA, setProfileA] = useState(null);
|
|
90
90
|
const [profileB, setProfileB] = useState(null);
|
|
91
91
|
const resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
|
|
92
|
-
const
|
|
92
|
+
const resetFlameGraphState = useResetFlameGraphState();
|
|
93
93
|
const sumByA = useSumByFromParams(sum_by_a);
|
|
94
94
|
const sumByB = useSumByFromParams(sum_by_b);
|
|
95
95
|
useEffect(() => {
|
|
@@ -156,7 +156,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
|
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
158
|
// Reset the state when a new search is performed.
|
|
159
|
-
|
|
159
|
+
resetFlameGraphState();
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
const mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
|
|
@@ -16,7 +16,7 @@ import cx from 'classnames';
|
|
|
16
16
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
17
17
|
import { useMeasure } from 'react-use';
|
|
18
18
|
import { FlameGraphSkeleton, SandwichFlameGraphSkeleton, useParcaContext, useURLState, } from '@parca/components';
|
|
19
|
-
import { testId } from '@parca/test-utils';
|
|
19
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
20
20
|
import { capitalizeOnlyFirstLetter, divide } from '@parca/utilities';
|
|
21
21
|
import DiffLegend from '../ProfileView/components/DiffLegend';
|
|
22
22
|
import { useProfileViewContext } from '../ProfileView/context/ProfileViewContext';
|
|
@@ -173,6 +173,6 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
|
|
|
173
173
|
}
|
|
174
174
|
return (_jsx(ErrorContent, { errorMessage: _jsxs(_Fragment, { children: [_jsx("span", { children: capitalizeOnlyFirstLetter(error.message) }), isFlameChart ? flamechartHelpText ?? null : null] }) }));
|
|
175
175
|
}
|
|
176
|
-
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, _jsx("div", { className: cx(!isInSandwichView ? 'min-h-48' : ''), id: "h-flame-graph", ...testId(
|
|
176
|
+
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, _jsx("div", { className: cx(!isInSandwichView ? 'min-h-48' : ''), id: "h-flame-graph", ...testId(TEST_IDS.FLAMEGRAPH_CONTAINER), children: _jsx(_Fragment, { children: flameGraph }) }), !isInSandwichView && (_jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] }))] }, "flame-graph-loaded") }));
|
|
177
177
|
};
|
|
178
178
|
export default ProfileFlameGraph;
|
|
@@ -16,7 +16,7 @@ import { Icon } from '@iconify/react';
|
|
|
16
16
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
17
17
|
import { MetricsGraphSkeleton, TextWithTooltip, useParcaContext, } from '@parca/components';
|
|
18
18
|
import { Query } from '@parca/parser';
|
|
19
|
-
import { testId } from '@parca/test-utils';
|
|
19
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
20
20
|
import { capitalizeOnlyFirstLetter, formatDate, timePattern, valueFormatter } from '@parca/utilities';
|
|
21
21
|
import { MergedProfileSelection } from '..';
|
|
22
22
|
import MetricsGraph from '../MetricsGraph';
|
|
@@ -268,9 +268,9 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to,
|
|
|
268
268
|
return (_jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [isDeltaType ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4 pr-3", children: "Per\u00A0Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit === 'nanoseconds' && sampleType === 'cpu'
|
|
269
269
|
? 'CPU Cores'
|
|
270
270
|
: sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.value ?? 0, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit, 5) })] })), originalPoint.duration != null &&
|
|
271
|
-
Number(originalPoint.duration) > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(Number(originalPoint.duration.toString()), 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(new Date(timestampMs), timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: utilizationMetrics ? (_jsxs(_Fragment, { children: [Object.keys(attributesResourceMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Resource Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesResourceMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(
|
|
271
|
+
Number(originalPoint.duration) > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(Number(originalPoint.duration.toString()), 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(new Date(timestampMs), timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: utilizationMetrics ? (_jsxs(_Fragment, { children: [Object.keys(attributesResourceMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Resource Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesResourceMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesResourceMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesResourceMap[name]}` }) }, name))) }), Object.keys(attributesMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesMap[name]}` }) }, name))) })] })) : (_jsx(_Fragment, { children: labels
|
|
272
272
|
.filter((label) => label.name !== '__name__')
|
|
273
|
-
.map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(
|
|
273
|
+
.map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}` }) }, label.name))) })) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }));
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
return null;
|
|
@@ -14,19 +14,19 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
import { Switch } from '@headlessui/react';
|
|
15
15
|
import Select from 'react-select';
|
|
16
16
|
import { Button, DateTimeRangePicker, useParcaContext } from '@parca/components';
|
|
17
|
-
import { testId } from '@parca/test-utils';
|
|
17
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
18
18
|
import MatchersInput from '../MatchersInput';
|
|
19
19
|
import ProfileTypeSelector from '../ProfileTypeSelector';
|
|
20
20
|
import SimpleMatchers from '../SimpleMatchers';
|
|
21
21
|
import ViewMatchers from '../ViewMatchers';
|
|
22
22
|
export function QueryControls({ showProfileTypeSelector, profileTypesData, profileTypesLoading, selectedProfileName, setProfileName, viewComponent, setQueryBrowserMode, advancedModeForQueryBrowser, setAdvancedModeForQueryBrowser, setMatchersString, setQueryExpression, query, queryBrowserRef, timeRangeSelection, setTimeRangeSelection, searchDisabled, queryClient, labels, sumBySelection, sumBySelectionLoading, setUserSumBySelection, sumByRef, profileType, showSumBySelector, profileTypesError, }) {
|
|
23
23
|
const { timezone } = useParcaContext();
|
|
24
|
-
return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", ...testId(
|
|
24
|
+
return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", ...testId(TEST_IDS.QUERY_CONTROLS_CONTAINER), children: [showProfileTypeSelector && (_jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.PROFILE_TYPE_LABEL), children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: profileTypesError, disabled: viewComponent?.disableProfileTypesDropdown })] })), _jsxs("div", { className: "w-full flex-1 flex flex-col gap-1 mt-auto", ref: queryBrowserRef, ...testId(TEST_IDS.QUERY_BROWSER_CONTAINER), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.QUERY_LABEL), children: "Query" }), viewComponent?.disableExplorativeQuerying !== true && (_jsxs(_Fragment, { children: [_jsxs(Switch, { checked: advancedModeForQueryBrowser, onChange: () => {
|
|
25
25
|
setAdvancedModeForQueryBrowser(!advancedModeForQueryBrowser);
|
|
26
26
|
setQueryBrowserMode(advancedModeForQueryBrowser ? 'simple' : 'advanced');
|
|
27
|
-
}, className: `${advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'} relative inline-flex h-[20px] w-[44px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75`, ...testId(
|
|
27
|
+
}, className: `${advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'} relative inline-flex h-[20px] w-[44px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75`, ...testId(TEST_IDS.ADVANCED_MODE_SWITCH), children: [_jsx("span", { className: "sr-only", children: "Use setting" }), _jsx("span", { "aria-hidden": "true", className: `${advancedModeForQueryBrowser ? 'translate-x-6' : 'translate-x-0'} pointer-events-none inline-block h-[16px] w-[16px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out` })] }), _jsx("label", { className: "text-xs", ...testId(TEST_IDS.QUERY_MODE_LABEL), children: "Advanced Mode" })] }))] }), viewComponent?.createViewComponent] }), viewComponent?.disableExplorativeQuerying === true &&
|
|
28
28
|
viewComponent?.labelnames !== undefined &&
|
|
29
|
-
viewComponent?.labelnames.length >= 1 ? (_jsx(ViewMatchers, { labelNames: viewComponent.labelnames, setMatchersString: setMatchersString, profileType: selectedProfileName, runQuery: setQueryExpression, currentQuery: query, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : advancedModeForQueryBrowser ? (_jsx(MatchersInput, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : (_jsx(SimpleMatchers, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryBrowserRef: queryBrowserRef, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() }, query.toString()))] }), showSumBySelector && (_jsxs("div", { ...testId(
|
|
29
|
+
viewComponent?.labelnames.length >= 1 ? (_jsx(ViewMatchers, { labelNames: viewComponent.labelnames, setMatchersString: setMatchersString, profileType: selectedProfileName, runQuery: setQueryExpression, currentQuery: query, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : advancedModeForQueryBrowser ? (_jsx(MatchersInput, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : (_jsx(SimpleMatchers, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryBrowserRef: queryBrowserRef, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() }, query.toString()))] }), showSumBySelector && (_jsxs("div", { ...testId(TEST_IDS.SUM_BY_CONTAINER), children: [_jsx("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: _jsx("label", { className: "text-xs", ...testId(TEST_IDS.SUM_BY_LABEL), children: "Sum by" }) }), _jsx(Select, { id: "h-sum-by-selector", "data-testid": testId(TEST_IDS.SUM_BY_SELECT)['data-testid'], defaultValue: [], isMulti: true, isClearable: false, name: "colors", options: labels.map(label => ({ label, value: label })), className: "parca-select-container text-sm w-full max-w-80", classNamePrefix: "parca-select", value: (sumBySelection ?? []).map(sumBy => ({ label: sumBy, value: sumBy })), onChange: newValue => {
|
|
30
30
|
setUserSumBySelection(newValue.map(option => option.value));
|
|
31
31
|
}, placeholder: "Labels...", styles: {
|
|
32
32
|
indicatorSeparator: () => ({ display: 'none' }),
|
|
@@ -49,8 +49,8 @@ export function QueryControls({ showProfileTypeSelector, profileTypesData, profi
|
|
|
49
49
|
setQueryExpression(true);
|
|
50
50
|
currentRef.blur();
|
|
51
51
|
}
|
|
52
|
-
} })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection, timezone: timezone, ...testId(
|
|
52
|
+
} })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection, timezone: timezone, ...testId(TEST_IDS.DATE_TIME_RANGE_PICKER) }), _jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.SEARCH_BUTTON_LABEL), children: "\u00A0" }), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
|
|
53
53
|
e.preventDefault();
|
|
54
54
|
setQueryExpression(true);
|
|
55
|
-
}, id: "h-matcher-search-button", ...testId(
|
|
55
|
+
}, id: "h-matcher-search-button", ...testId(TEST_IDS.SEARCH_BUTTON), children: "Search" })] })] }));
|
|
56
56
|
}
|
|
@@ -13,7 +13,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
import { useMemo } from 'react';
|
|
15
15
|
import { Select } from '@parca/components';
|
|
16
|
-
import { testId } from '@parca/test-utils';
|
|
16
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
17
17
|
export const wellKnownProfiles = {
|
|
18
18
|
'block:contentions:count:contentions:count': {
|
|
19
19
|
name: 'Block Contentions Total',
|
|
@@ -139,6 +139,6 @@ const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selecte
|
|
|
139
139
|
key: name,
|
|
140
140
|
element: profileSelectElement(name, flexibleKnownProfilesDetection),
|
|
141
141
|
}));
|
|
142
|
-
return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled, ...testId(
|
|
142
|
+
return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled, ...testId(TEST_IDS.PROFILE_TYPE_SELECTOR) }));
|
|
143
143
|
};
|
|
144
144
|
export default ProfileTypeSelector;
|
|
@@ -15,8 +15,6 @@ interface GetDashboardItemProps {
|
|
|
15
15
|
profileSource: ProfileSource;
|
|
16
16
|
total: bigint;
|
|
17
17
|
filtered: bigint;
|
|
18
|
-
curPath: string[];
|
|
19
|
-
setNewCurPath: (path: string[]) => void;
|
|
20
18
|
curPathArrow: CurrentPathFrame[];
|
|
21
19
|
setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
|
|
22
20
|
perf?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
|
|
@@ -15,7 +15,7 @@ import { Fragment, useState } from 'react';
|
|
|
15
15
|
import { Popover, Transition } from '@headlessui/react';
|
|
16
16
|
import { usePopper } from 'react-popper';
|
|
17
17
|
import { selectDarkMode, useAppSelector } from '@parca/store';
|
|
18
|
-
import { testId } from '@parca/test-utils';
|
|
18
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
19
19
|
import { getIncreasedSpanColor, getNewSpanColor, getReducedSpanColor } from '@parca/utilities';
|
|
20
20
|
const transparencyValues = [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100];
|
|
21
21
|
const DiffLegendBar = ({ onMouseEnter, onMouseLeave, }) => {
|
|
@@ -46,6 +46,6 @@ const DiffLegend = () => {
|
|
|
46
46
|
const handleMouseLeave = () => {
|
|
47
47
|
setShowLegendTooltip(false);
|
|
48
48
|
};
|
|
49
|
-
return (_jsxs("div", { className: "mt-1 mb-2 hidden md:block", id: "h-diff-legend", ...testId(
|
|
49
|
+
return (_jsxs("div", { className: "mt-1 mb-2 hidden md:block", id: "h-diff-legend", ...testId(TEST_IDS.DIFF_LEGEND), children: [_jsxs("div", { ref: setReferenceElement, className: "flex items-center justify-center", children: [_jsx("span", { children: "Better" }), _jsx(DiffLegendBar, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }), _jsx("span", { children: "Worse" })] }), _jsx(Popover, { className: "relative", children: () => (_jsx(Transition, { show: showLegendTooltip, as: Fragment, enter: "transition ease-out duration-200", enterFrom: "opacity-0 translate-y-1", enterTo: "opacity-100 translate-y-0", leave: "transition ease-in duration-150", leaveFrom: "opacity-100 translate-y-0", leaveTo: "opacity-0 translate-y-1", children: _jsx(Popover.Panel, { ref: setPopperElement, style: styles.popper, ...attributes.popper, children: _jsx("div", { className: "overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "bg-gray-50 p-4 dark:bg-gray-800", children: [_jsx("div", { className: "flex items-center justify-center" }), _jsx("span", { className: "block text-sm text-gray-500 dark:text-gray-50", children: "This is a differential flame graph, where a purple-colored node means unchanged, and the darker the red, the worse the node got, and the darker the green, the better the node got." })] }) }) }) })) })] }));
|
|
50
50
|
};
|
|
51
51
|
export default DiffLegend;
|
|
@@ -12,12 +12,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
import Select from 'react-select';
|
|
15
|
-
import { testId } from '@parca/test-utils';
|
|
15
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
16
16
|
import { FIELD_LABELS } from '../../../ProfileFlameGraph/FlameGraphArrow';
|
|
17
17
|
const GroupByLabelsDropdown = ({ labels, groupBy, setGroupByLabels }) => {
|
|
18
|
-
return (_jsxs("div", { className: "flex flex-col relative", ...testId(
|
|
18
|
+
return (_jsxs("div", { className: "flex flex-col relative", ...testId(TEST_IDS.GROUP_BY_CONTAINER), children: [_jsx("div", { className: "flex items-center justify-between", children: _jsx("label", { className: "text-sm", ...testId(TEST_IDS.GROUP_BY_LABEL), children: "Group by" }) }), _jsx(Select, { isMulti: true, defaultMenuIsOpen: false, defaultValue: undefined, name: "labels", options: labels.map(label => ({ label, value: `${FIELD_LABELS}.${label}` })), className: "parca-select-container text-sm rounded-md bg-white", classNamePrefix: "parca-select", components: {
|
|
19
19
|
// eslint-disable-next-line react/prop-types
|
|
20
|
-
MenuList: ({ children, innerProps }) => (_jsx("div", { className: "overflow-y-auto", ...testId(
|
|
20
|
+
MenuList: ({ children, innerProps }) => (_jsx("div", { className: "overflow-y-auto", ...testId(TEST_IDS.GROUP_BY_SELECT_FLYOUT), ...innerProps,
|
|
21
21
|
// eslint-disable-next-line react/prop-types
|
|
22
22
|
style: { ...innerProps.style, height: '332px', maxHeight: '332px', fontSize: '14px' }, children: children })),
|
|
23
23
|
}, value: groupBy
|
|
@@ -15,7 +15,7 @@ import { useCallback } from 'react';
|
|
|
15
15
|
import { Icon } from '@iconify/react';
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import { Button, Input, Select } from '@parca/components';
|
|
18
|
-
import { testId } from '@parca/test-utils';
|
|
18
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
19
19
|
import { useProfileViewContext } from '../../context/ProfileViewContext';
|
|
20
20
|
import { getPresetByKey, getPresetsForProfileType, isPresetKey } from './filterPresets';
|
|
21
21
|
import { useProfileFilters } from './useProfileFilters';
|
|
@@ -155,11 +155,11 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
|
|
|
155
155
|
}
|
|
156
156
|
}, [onApplyFilters]);
|
|
157
157
|
const filtersToRender = localFilters.length > 0 ? localFilters : appliedFilters ?? [];
|
|
158
|
-
return (_jsxs("div", { className: "flex gap-2 w-full items-start", ...testId(
|
|
158
|
+
return (_jsxs("div", { className: "flex gap-2 w-full items-start", ...testId(TEST_IDS.PROFILE_FILTERS_CONTAINER), children: [_jsxs("div", { className: "flex-1 flex flex-wrap gap-2", children: [filtersToRender.map(filter => {
|
|
159
159
|
const isNumberField = filter.field === 'address' || filter.field === 'line_number';
|
|
160
160
|
const matchTypeItems = isNumberField ? numberMatchTypeItems : stringMatchTypeItems;
|
|
161
161
|
const isPresetFilter = filter.type != null && isPresetKey(filter.type);
|
|
162
|
-
return (_jsxs("div", { className: "flex items-center gap-0", children: [_jsx(Select, { items: filterTypeItems, selectedKey: filter.type, placeholder: "Select Filter", disabled: readOnly, ...testId(
|
|
162
|
+
return (_jsxs("div", { className: "flex items-center gap-0", children: [_jsx(Select, { items: filterTypeItems, selectedKey: filter.type, placeholder: "Select Filter", disabled: readOnly, ...testId(TEST_IDS.FILTER_TYPE_SELECT), flyoutTestId: "filter-type-select-flyout", onSelection: key => {
|
|
163
163
|
// Check if this is a preset selection
|
|
164
164
|
if (isPresetKey(key)) {
|
|
165
165
|
const preset = getPresetByKey(key);
|
|
@@ -191,7 +191,7 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
|
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
}, className: cx('gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1', readOnly && isPresetFilter ? 'rounded-md' : 'rounded-l-md rounded-r-none', !readOnly && (isPresetFilter ? 'rounded-r-none border-r-0' : 'rounded-r-none'), readOnly ? 'w-auto' : filter.type != null ? 'border-r-0 w-auto' : 'w-32'), hideCaretDropdown: readOnly }), filter.type != null && !isPresetFilter && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', disabled: readOnly, ...testId(
|
|
194
|
+
}, className: cx('gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1', readOnly && isPresetFilter ? 'rounded-md' : 'rounded-l-md rounded-r-none', !readOnly && (isPresetFilter ? 'rounded-r-none border-r-0' : 'rounded-r-none'), readOnly ? 'w-auto' : filter.type != null ? 'border-r-0 w-auto' : 'w-32'), hideCaretDropdown: readOnly }), filter.type != null && !isPresetFilter && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', disabled: readOnly, ...testId(TEST_IDS.FILTER_FIELD_SELECT), flyoutTestId: "filter-field-select-flyout", onSelection: key => {
|
|
195
195
|
const newField = key;
|
|
196
196
|
const isNewFieldNumber = newField === 'address' || newField === 'line_number';
|
|
197
197
|
const isCurrentFieldNumber = filter.field === 'address' || filter.field === 'line_number';
|
|
@@ -204,7 +204,7 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
|
|
|
204
204
|
else {
|
|
205
205
|
updateFilter(filter.id, { field: newField });
|
|
206
206
|
}
|
|
207
|
-
}, className: cx('rounded-none border-r-0 w-32 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Select, { items: matchTypeItems, selectedKey: filter.matchType ?? '', disabled: readOnly, ...testId(
|
|
207
|
+
}, className: cx('rounded-none border-r-0 w-32 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Select, { items: matchTypeItems, selectedKey: filter.matchType ?? '', disabled: readOnly, ...testId(TEST_IDS.FILTER_MATCH_TYPE_SELECT), flyoutTestId: "filter-match-type-select-flyout", onSelection: key => updateFilter(filter.id, { matchType: key }), className: cx('rounded-none border-r-0 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Input, { placeholder: "Value", value: filter.value, disabled: readOnly, onChange: e => updateFilter(filter.id, { value: e.target.value }), onKeyDown: handleKeyDown, className: "rounded-none w-36 text-sm focus:outline-1", ...testId(TEST_IDS.FILTER_VALUE_INPUT) })] })), !readOnly && (_jsx(Button, { variant: "neutral", ...testId(TEST_IDS.FILTER_REMOVE_BUTTON), onClick: () => {
|
|
208
208
|
// If we're displaying local filters and this is the last one, reset everything
|
|
209
209
|
if (localFilters.length > 0 && localFilters.length === 1) {
|
|
210
210
|
resetFilters();
|
|
@@ -220,6 +220,6 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
|
|
|
220
220
|
}, className: cx('h-[38px] p-3', filter.type != null
|
|
221
221
|
? 'rounded-none rounded-r-md'
|
|
222
222
|
: 'rounded-l-none rounded-r-md'), children: _jsx(Icon, { icon: "mdi:close", className: "h-4 w-4" }) }))] }, filter.id));
|
|
223
|
-
}), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", ...testId(
|
|
223
|
+
}), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", ...testId(TEST_IDS.ADD_FILTER_BUTTON), children: _jsx(Icon, { icon: "mdi:filter-plus-outline", className: "h-4 w-4" }) })), !readOnly && localFilters.length === 0 && (appliedFilters?.length ?? 0) === 0 && (_jsxs(Button, { variant: "neutral", onClick: addFilter, className: "flex items-center gap-2", ...testId(TEST_IDS.ADD_FILTER_BUTTON), children: [_jsx(Icon, { icon: "mdi:filter-outline", className: "h-4 w-4" }), _jsx("span", { children: "Filter" })] }))] }), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "primary", onClick: onApplyFilters, disabled: !hasUnsavedChanges || !localFilters.some(isFilterComplete), className: cx('flex items-center gap-2 sticky top-0'), ...testId(TEST_IDS.APPLY_FILTERS_BUTTON), children: _jsx("span", { children: "Apply" }) }))] }));
|
|
224
224
|
};
|
|
225
225
|
export default ProfileFilters;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;AAMtF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5F,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,EAAE,KAAG,aAAa,EA+E7E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAmF7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CA2L1B,CAAC"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
|
+
import { useResetFlameGraphState } from '../../hooks/useResetFlameGraphState';
|
|
14
15
|
import { getPresetByKey, isPresetKey } from './filterPresets';
|
|
15
16
|
import { useProfileFiltersUrlState } from './useProfileFiltersUrlState';
|
|
16
17
|
const createStringCondition = (matchType, value) => ({
|
|
@@ -182,6 +183,7 @@ export const convertToProtoFilters = (profileFilters) => {
|
|
|
182
183
|
};
|
|
183
184
|
export const useProfileFilters = () => {
|
|
184
185
|
const { appliedFilters, setAppliedFilters } = useProfileFiltersUrlState();
|
|
186
|
+
const resetFlameGraphState = useResetFlameGraphState();
|
|
185
187
|
const [localFilters, setLocalFilters] = useState(appliedFilters ?? []);
|
|
186
188
|
const lastAppliedFiltersRef = useRef([]);
|
|
187
189
|
const localFiltersRef = useRef(localFilters);
|
|
@@ -259,9 +261,10 @@ export const useProfileFilters = () => {
|
|
|
259
261
|
// Auto-apply the filter since it has a value
|
|
260
262
|
const filtersToApply = [...(appliedFilters ?? []), newFilter];
|
|
261
263
|
setAppliedFilters(filtersToApply);
|
|
264
|
+
resetFlameGraphState();
|
|
262
265
|
},
|
|
263
266
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
264
|
-
[setAppliedFilters]);
|
|
267
|
+
[setAppliedFilters, resetFlameGraphState]);
|
|
265
268
|
const removeExcludeBinary = useCallback((binaryName) => {
|
|
266
269
|
// Search for the exclude filter (not_contains) for this binary
|
|
267
270
|
const filterToRemove = (appliedFilters ?? []).find(f => f.type === 'frame' &&
|
|
@@ -272,10 +275,11 @@ export const useProfileFilters = () => {
|
|
|
272
275
|
// Remove the filter from applied filters
|
|
273
276
|
const updatedAppliedFilters = (appliedFilters ?? []).filter(f => f.id !== filterToRemove.id);
|
|
274
277
|
setAppliedFilters(updatedAppliedFilters);
|
|
278
|
+
resetFlameGraphState();
|
|
275
279
|
// Also remove from local filters
|
|
276
280
|
setLocalFilters(localFiltersRef.current.filter(f => f.id !== filterToRemove.id));
|
|
277
281
|
}
|
|
278
|
-
}, [appliedFilters, setAppliedFilters]);
|
|
282
|
+
}, [appliedFilters, setAppliedFilters, resetFlameGraphState]);
|
|
279
283
|
const removeFilter = useCallback((id) => {
|
|
280
284
|
setLocalFilters(localFiltersRef.current.filter(f => f.id !== id));
|
|
281
285
|
}, []);
|
|
@@ -285,7 +289,8 @@ export const useProfileFilters = () => {
|
|
|
285
289
|
const resetFilters = useCallback(() => {
|
|
286
290
|
setLocalFilters([]);
|
|
287
291
|
setAppliedFilters([]);
|
|
288
|
-
|
|
292
|
+
resetFlameGraphState();
|
|
293
|
+
}, [setAppliedFilters, resetFlameGraphState]);
|
|
289
294
|
const onApplyFilters = useCallback(() => {
|
|
290
295
|
const validFilters = localFiltersRef.current.filter(f => {
|
|
291
296
|
// For preset filters, only need type and value
|
|
@@ -300,7 +305,8 @@ export const useProfileFilters = () => {
|
|
|
300
305
|
id: `filter-${Date.now()}-${index}`,
|
|
301
306
|
}));
|
|
302
307
|
setAppliedFilters(filtersToApply);
|
|
303
|
-
|
|
308
|
+
resetFlameGraphState();
|
|
309
|
+
}, [setAppliedFilters, resetFlameGraphState]);
|
|
304
310
|
const protoFilters = useMemo(() => {
|
|
305
311
|
return convertToProtoFilters(appliedFilters ?? []);
|
|
306
312
|
}, [appliedFilters]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Icon } from '@iconify/react';
|
|
3
3
|
import { Button } from '@parca/components';
|
|
4
|
-
import { testId } from '@parca/test-utils';
|
|
4
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
5
5
|
import { useDashboard } from '../../context/DashboardContext';
|
|
6
6
|
import GroupByDropdown from '../ActionButtons/GroupByDropdown';
|
|
7
7
|
import InvertCallStack from '../InvertCallStack';
|
|
@@ -14,7 +14,7 @@ export const TableToolbar = ({ profileType, total, filtered }) => {
|
|
|
14
14
|
return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsx(TableColumnsDropdown, { profileType: profileType, total: total, filtered: filtered }) }) }));
|
|
15
15
|
};
|
|
16
16
|
export const FlameGraphToolbar = ({ curPath, setNewCurPath }) => {
|
|
17
|
-
return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsxs(Button, { variant: "neutral", className: "gap-2 w-max h-fit", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, id: "h-reset-graph", ...testId(
|
|
17
|
+
return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsxs(Button, { variant: "neutral", className: "gap-2 w-max h-fit", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, id: "h-reset-graph", ...testId(TEST_IDS.FLAMEGRAPH_RESET_BUTTON), children: ["Reset graph", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }) }) }));
|
|
18
18
|
};
|
|
19
19
|
export const SandwichFlameGraphToolbar = ({ resetSandwichFunctionName, sandwichFunctionName, }) => {
|
|
20
20
|
return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end justify-between", children: _jsx(Button, { color: "neutral", onClick: () => resetSandwichFunctionName(), className: "w-auto", variant: "neutral", disabled: sandwichFunctionName === undefined || sandwichFunctionName.length === 0, children: "Reset view" }) }) }));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResetFlameGraphState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetFlameGraphState.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,QAAO,CAAC,MAAM,IAAI,CAWrD,CAAC"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { useURLState } from '@parca/components';
|
|
14
|
-
export const
|
|
14
|
+
export const useResetFlameGraphState = () => {
|
|
15
15
|
const [val, setCurPath] = useURLState('cur_path');
|
|
16
16
|
return () => {
|
|
17
17
|
setTimeout(() => {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { CurrentPathFrame } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
2
2
|
export declare const useVisualizationState: () => {
|
|
3
|
-
curPath: string[];
|
|
4
|
-
setCurPath: (path: string[]) => void;
|
|
5
3
|
curPathArrow: CurrentPathFrame[];
|
|
6
4
|
setCurPathArrow: (path: CurrentPathFrame[]) => void;
|
|
7
5
|
colorStackLegend: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;AAG/E,eAAO,MAAM,qBAAqB,QAAO;IACvC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACpD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,EAAE,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5E,yBAAyB,EAAE,MAAM,IAAI,CAAC;CA0EvC,CAAC"}
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
|
-
import { useCallback, useMemo
|
|
13
|
+
import { useCallback, useMemo } from 'react';
|
|
14
14
|
import { JSONParser, JSONSerializer, useURLState, useURLStateCustom } from '@parca/components';
|
|
15
15
|
import { FIELD_FUNCTION_FILE_NAME, FIELD_FUNCTION_NAME, FIELD_LABELS, FIELD_LOCATION_ADDRESS, FIELD_MAPPING_FILE, } from '../../ProfileFlameGraph/FlameGraphArrow';
|
|
16
|
+
import { useResetFlameGraphState } from './useResetFlameGraphState';
|
|
16
17
|
export const useVisualizationState = () => {
|
|
17
|
-
const [curPath, setCurPath] = useState([]);
|
|
18
18
|
const [curPathArrow, setCurPathArrow] = useURLStateCustom('cur_path', {
|
|
19
19
|
parse: (JSONParser),
|
|
20
20
|
stringify: JSONSerializer,
|
|
@@ -27,6 +27,7 @@ export const useVisualizationState = () => {
|
|
|
27
27
|
alwaysReturnArray: true,
|
|
28
28
|
});
|
|
29
29
|
const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
|
|
30
|
+
const resetFlameGraphState = useResetFlameGraphState();
|
|
30
31
|
const levelsOfProfiling = useMemo(() => [
|
|
31
32
|
FIELD_FUNCTION_NAME,
|
|
32
33
|
FIELD_FUNCTION_FILE_NAME,
|
|
@@ -44,7 +45,8 @@ export const useVisualizationState = () => {
|
|
|
44
45
|
const filteredGroupBy = groupBy.filter(item => !levelsOfProfiling.includes(item));
|
|
45
46
|
setGroupBy([...filteredGroupBy, key]); // add
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
resetFlameGraphState();
|
|
49
|
+
}, [groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState]);
|
|
48
50
|
const setGroupByLabels = useCallback((labels) => {
|
|
49
51
|
setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
|
|
50
52
|
}, [groupBy, setGroupBy]);
|
|
@@ -52,8 +54,6 @@ export const useVisualizationState = () => {
|
|
|
52
54
|
setSandwichFunctionName(undefined);
|
|
53
55
|
}, [setSandwichFunctionName]);
|
|
54
56
|
return {
|
|
55
|
-
curPath,
|
|
56
|
-
setCurPath,
|
|
57
57
|
curPathArrow,
|
|
58
58
|
setCurPathArrow,
|
|
59
59
|
colorStackLegend,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA2HzB,CAAC"}
|