@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
|
@@ -26,7 +26,7 @@ import { useVisualizationState } from './hooks/useVisualizationState';
|
|
|
26
26
|
export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, sandwichData, }) => {
|
|
27
27
|
const { timezone, perf, profileViewExternalMainActions, preferencesModal, profileViewExternalSubActions, } = useParcaContext();
|
|
28
28
|
const { ref, dimensions } = useContainerDimensions();
|
|
29
|
-
const {
|
|
29
|
+
const { curPathArrow, setCurPathArrow, colorStackLegend, colorBy, groupBy, toggleGroupBy, setGroupByLabels, sandwichFunctionName, resetSandwichFunctionName, } = useVisualizationState();
|
|
30
30
|
const { colorMappings } = useProfileMetadata({
|
|
31
31
|
flamegraphArrow: flamegraphData.arrow,
|
|
32
32
|
metadataMappingFiles: flamegraphData.metadataMappingFiles,
|
|
@@ -49,8 +49,6 @@ export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, t
|
|
|
49
49
|
profileSource,
|
|
50
50
|
total,
|
|
51
51
|
filtered,
|
|
52
|
-
curPath,
|
|
53
|
-
setNewCurPath: setCurPath,
|
|
54
52
|
curPathArrow,
|
|
55
53
|
setNewCurPathArrow: setCurPathArrow,
|
|
56
54
|
perf,
|
|
@@ -39,7 +39,7 @@ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizat
|
|
|
39
39
|
const { protoFilters } = useProfileFilters();
|
|
40
40
|
useEffect(() => {
|
|
41
41
|
// If profile type is not delta, remove flamechart from the dashboard items
|
|
42
|
-
// and set it to flame if no other items are selected.
|
|
42
|
+
// and set it to flame graph if no other items are selected.
|
|
43
43
|
if (profileSource == null) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
@@ -16,7 +16,7 @@ import { Icon } from '@iconify/react';
|
|
|
16
16
|
import { useQueryClient } from '@tanstack/react-query';
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
import { useGrpcMetadata } from '@parca/components';
|
|
19
|
-
import { testId } from '@parca/test-utils';
|
|
19
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
20
20
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
21
21
|
import { LabelProvider, useLabels } from '../contexts/SimpleMatchersLabelContext';
|
|
22
22
|
import { useUtilizationLabels } from '../contexts/UtilizationLabelsContext';
|
|
@@ -242,9 +242,9 @@ const SimpleMatchers = ({ queryClient, setMatchersString, currentQuery, profileT
|
|
|
242
242
|
};
|
|
243
243
|
}, [queryRows, fetchLabelValuesUnified]);
|
|
244
244
|
const isRowRegex = (row) => row.operator === '=~' || row.operator === '!~';
|
|
245
|
-
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", ...testId(
|
|
245
|
+
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", ...testId(TEST_IDS.SIMPLE_MATCHERS_CONTAINER), children: [visibleRows.map((row, index) => (_jsxs("div", { className: "flex items-center", ...testId(TEST_IDS.SIMPLE_MATCHER_ROW), children: [_jsx(Select, { items: labelNameOptions, onSelection: value => handleUpdateRow(index, 'labelName', value), placeholder: "Select label name", selectedKey: row.labelName, className: "rounded-tr-none rounded-br-none ring-0 focus:ring-0 outline-none", loading: labelNamesLoading, searchable: true, ...testId(TEST_IDS.LABEL_NAME_SELECT) }), _jsx(Select, { items: operatorOptions, onSelection: value => handleUpdateRow(index, 'operator', value), selectedKey: row.operator, className: "rounded-none ring-0 focus:ring-0 outline-none", ...testId(TEST_IDS.OPERATOR_SELECT) }), _jsx(Select, { items: transformLabelsForSelect(row.labelValues), onSelection: value => handleUpdateRow(index, 'labelValue', value), placeholder: "Select label value", selectedKey: row.labelValue, className: "rounded-none ring-0 focus:ring-0 outline-none max-w-48", optionsClassname: cx('max-w-[300px]', {
|
|
246
246
|
'w-[300px]': isRowRegex(row),
|
|
247
|
-
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row), ...testId(
|
|
247
|
+
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row), ...testId(TEST_IDS.LABEL_VALUE_SELECT) }), _jsx("button", { onClick: () => removeRow(index), className: cx('p-2 border-gray-200 border rounded rounded-tl-none rounded-bl-none focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900'), ...testId(TEST_IDS.REMOVE_MATCHER_BUTTON), children: _jsx(Icon, { icon: "carbon:close", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) })] }, index))), queryRows.length > 3 && (_jsx("button", { onClick: () => setShowAll(!showAll), className: "mr-2 px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900", ...testId(showAll ? TEST_IDS.SHOW_LESS_BUTTON : TEST_IDS.SHOW_MORE_BUTTON), children: showAll ? 'Show less' : `Show ${hiddenRowsCount} more` })), _jsx("button", { onClick: addNewRow, className: "p-2 border-gray-200 dark:bg-gray-900 dark:border-gray-600 border rounded focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500", ...testId(TEST_IDS.ADD_MATCHER_BUTTON), children: _jsx(Icon, { icon: "material-symbols:add", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) })] }));
|
|
248
248
|
};
|
|
249
249
|
export default function SimpleMathersWithProvider(props) {
|
|
250
250
|
const labelNameFromMatchers = useMemo(() => {
|
|
@@ -15,7 +15,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
15
15
|
import { Icon } from '@iconify/react';
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import { useGrpcMetadata } from '@parca/components';
|
|
18
|
-
import { testId } from '@parca/test-utils';
|
|
18
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
19
19
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
20
20
|
import CustomSelect from '../SimpleMatchers/Select';
|
|
21
21
|
const ViewMatchers = ({ labelNames, profileType, queryClient, runQuery, setMatchersString, start, end, currentQuery, }) => {
|
|
@@ -112,6 +112,6 @@ const ViewMatchers = ({ labelNames, profileType, queryClient, runQuery, setMatch
|
|
|
112
112
|
element: { active: _jsx(_Fragment, { children: value }), expanded: _jsx(_Fragment, { children: value }) },
|
|
113
113
|
}));
|
|
114
114
|
}, []);
|
|
115
|
-
return (_jsx("div", { className: "flex flex-wrap gap-2", ...testId(
|
|
115
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2", ...testId(TEST_IDS.VIEW_MATCHERS_CONTAINER), children: labelNames.map(labelName => (_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "relative border shadow-sm px-4 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 text-sm flex gap-2 items-center justify-between bg-gray-100 dark:bg-gray-700 rounded-l-md border-gray-300 dark:border-gray-600", children: labelName }), _jsx(CustomSelect, { searchable: true, placeholder: "Select value", items: transformValuesForSelect(labelValuesMap[labelName] ?? []), onSelection: (value) => handleSelection(labelName, value), selectedKey: selectionsRef.current[labelName] ?? undefined, className: cx('rounded-l-none border-l-0', selectionsRef.current[labelName] != null && 'border-r-0 rounded-r-none'), loading: isLoading[labelName] ?? false }), selectionsRef.current[labelName] != null && (_jsx("button", { onClick: () => handleReset(labelName), className: "p-2 border-gray-200 bg-white dark:bg-gray-900 dark:border-gray-600 border rounded-r-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500", "aria-label": `Reset ${labelName} selection`, children: _jsx(Icon, { icon: "mdi:close", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) }))] }, labelName))) }));
|
|
116
116
|
};
|
|
117
117
|
export default ViewMatchers;
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.54",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@floating-ui/react": "^0.27.12",
|
|
7
7
|
"@headlessui/react": "^1.7.19",
|
|
8
8
|
"@iconify/react": "^4.0.0",
|
|
9
9
|
"@parca/client": "0.17.5",
|
|
10
|
-
"@parca/components": "0.16.
|
|
10
|
+
"@parca/components": "0.16.371",
|
|
11
11
|
"@parca/dynamicsize": "0.16.67",
|
|
12
12
|
"@parca/hooks": "0.0.102",
|
|
13
13
|
"@parca/icons": "0.16.74",
|
|
14
14
|
"@parca/parser": "0.16.81",
|
|
15
15
|
"@parca/store": "0.16.186",
|
|
16
|
-
"@parca/test-utils": "0.0.
|
|
16
|
+
"@parca/test-utils": "0.0.13",
|
|
17
17
|
"@parca/utilities": "0.0.109",
|
|
18
18
|
"@popperjs/core": "^2.11.8",
|
|
19
19
|
"@protobuf-ts/runtime-rpc": "^2.5.0",
|
|
@@ -79,5 +79,5 @@
|
|
|
79
79
|
"access": "public",
|
|
80
80
|
"registry": "https://registry.npmjs.org/"
|
|
81
81
|
},
|
|
82
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "842199b0933536a1d704de0fbcac61f8b365d41e"
|
|
83
83
|
}
|
|
@@ -20,7 +20,7 @@ import TextareaAutosize from 'react-textarea-autosize';
|
|
|
20
20
|
import {LabelsRequest, LabelsResponse, QueryServiceClient, ValuesRequest} from '@parca/client';
|
|
21
21
|
import {useGrpcMetadata} from '@parca/components';
|
|
22
22
|
import {Query} from '@parca/parser';
|
|
23
|
-
import {testId} from '@parca/test-utils';
|
|
23
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
24
24
|
import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
|
|
25
25
|
|
|
26
26
|
import {UtilizationLabels} from '../ProfileSelector';
|
|
@@ -292,7 +292,7 @@ const MatchersInput = ({
|
|
|
292
292
|
return (
|
|
293
293
|
<div
|
|
294
294
|
className="w-full min-w-[300px] flex-1 font-mono relative"
|
|
295
|
-
{...testId(
|
|
295
|
+
{...testId(TEST_IDS.MATCHERS_INPUT_CONTAINER)}
|
|
296
296
|
>
|
|
297
297
|
<TextareaAutosize
|
|
298
298
|
ref={inputRef}
|
|
@@ -308,7 +308,7 @@ const MatchersInput = ({
|
|
|
308
308
|
onChange={onChange}
|
|
309
309
|
value={value}
|
|
310
310
|
onBlur={unfocus}
|
|
311
|
-
{...testId(
|
|
311
|
+
{...testId(TEST_IDS.MATCHERS_TEXTAREA)}
|
|
312
312
|
onFocus={focus}
|
|
313
313
|
disabled={profileSelected} // Disable input if no profile has been selected
|
|
314
314
|
title={
|
|
@@ -15,7 +15,7 @@ import {Icon} from '@iconify/react';
|
|
|
15
15
|
import {Item, Menu, Submenu} from 'react-contexify';
|
|
16
16
|
|
|
17
17
|
import {useParcaContext} from '@parca/components';
|
|
18
|
-
import {testId} from '@parca/test-utils';
|
|
18
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
19
19
|
|
|
20
20
|
import {Series, SeriesPoint} from '../';
|
|
21
21
|
|
|
@@ -115,7 +115,7 @@ const MetricsContextMenu = ({
|
|
|
115
115
|
id={menuId}
|
|
116
116
|
onVisibilityChange={trackVisibility}
|
|
117
117
|
theme={isDarkMode ? 'dark' : ''}
|
|
118
|
-
{...testId(
|
|
118
|
+
{...testId(TEST_IDS.METRICS_GRAPH_CONTEXT_MENU)}
|
|
119
119
|
>
|
|
120
120
|
{menuItems.map(renderMenuItem)}
|
|
121
121
|
</Menu>
|
|
@@ -15,7 +15,7 @@ import {useEffect, useMemo, useState} from 'react';
|
|
|
15
15
|
|
|
16
16
|
import {usePopper} from 'react-popper';
|
|
17
17
|
|
|
18
|
-
import {testId} from '@parca/test-utils';
|
|
18
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
19
19
|
|
|
20
20
|
interface VirtualElement {
|
|
21
21
|
getBoundingClientRect: () => DOMRect;
|
|
@@ -113,7 +113,7 @@ const MetricsTooltip = ({x, y, contextElement, content}: Props): JSX.Element =>
|
|
|
113
113
|
ref={setPopperElement}
|
|
114
114
|
style={styles.popper}
|
|
115
115
|
{...attributes.popper}
|
|
116
|
-
{...testId(
|
|
116
|
+
{...testId(TEST_IDS.METRICS_GRAPH_TOOLTIP)}
|
|
117
117
|
className="z-50"
|
|
118
118
|
>
|
|
119
119
|
<div className="flex max-w-lg">
|
|
@@ -19,7 +19,7 @@ import throttle from 'lodash.throttle';
|
|
|
19
19
|
import {useContextMenu} from 'react-contexify';
|
|
20
20
|
|
|
21
21
|
import {DateTimeRange, useParcaContext} from '@parca/components';
|
|
22
|
-
import {testId} from '@parca/test-utils';
|
|
22
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
23
23
|
import {formatDate, formatForTimespan, getPrecision, valueFormatter} from '@parca/utilities';
|
|
24
24
|
|
|
25
25
|
import MetricsCircle from '../MetricsCircle';
|
|
@@ -84,7 +84,7 @@ const MetricsGraph = ({
|
|
|
84
84
|
return (
|
|
85
85
|
<div
|
|
86
86
|
className="relative"
|
|
87
|
-
{...testId(
|
|
87
|
+
{...testId(TEST_IDS.METRICS_GRAPH)}
|
|
88
88
|
onClick={() => isInfoPanelOpen && setIsInfoPanelOpen(false)}
|
|
89
89
|
>
|
|
90
90
|
<div className="absolute right-0 top-0">
|
|
@@ -16,7 +16,7 @@ import {useState} from 'react';
|
|
|
16
16
|
import {QueryServiceClient} from '@parca/client';
|
|
17
17
|
import {useURLState} 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 type {NavigateFunction} from '@parca/utilities';
|
|
21
21
|
|
|
22
22
|
import {ProfileDiffSource, ProfileSelection, ProfileViewWithData} from '..';
|
|
@@ -64,9 +64,12 @@ const ProfileExplorerCompare = ({
|
|
|
64
64
|
const [compareAbsolute] = useURLState('compare_absolute');
|
|
65
65
|
|
|
66
66
|
return (
|
|
67
|
-
<div {...testId(
|
|
67
|
+
<div {...testId(TEST_IDS.COMPARE_CONTAINER)}>
|
|
68
68
|
<div className="flex justify-between gap-2 relative mb-2">
|
|
69
|
-
<div
|
|
69
|
+
<div
|
|
70
|
+
className="flex-column flex-1 p-2 shadow-md rounded-md"
|
|
71
|
+
{...testId(TEST_IDS.COMPARE_SIDE_A)}
|
|
72
|
+
>
|
|
70
73
|
<ProfileSelector
|
|
71
74
|
queryClient={queryClient}
|
|
72
75
|
querySelection={queryA}
|
|
@@ -82,7 +85,10 @@ const ProfileExplorerCompare = ({
|
|
|
82
85
|
setDisplayHideMetricsGraphButton={setShowMetricsGraph}
|
|
83
86
|
/>
|
|
84
87
|
</div>
|
|
85
|
-
<div
|
|
88
|
+
<div
|
|
89
|
+
className="flex-column flex-1 p-2 shadow-md rounded-md"
|
|
90
|
+
{...testId(TEST_IDS.COMPARE_SIDE_B)}
|
|
91
|
+
>
|
|
86
92
|
<ProfileSelector
|
|
87
93
|
queryClient={queryClient}
|
|
88
94
|
querySelection={queryB}
|
|
@@ -101,7 +107,7 @@ const ProfileExplorerCompare = ({
|
|
|
101
107
|
</div>
|
|
102
108
|
<div className="grid grid-cols-1">
|
|
103
109
|
{profileA != null && profileB != null ? (
|
|
104
|
-
<div {...testId(
|
|
110
|
+
<div {...testId(TEST_IDS.COMPARE_PROFILE_VIEW)}>
|
|
105
111
|
<ProfileViewWithData
|
|
106
112
|
queryClient={queryClient}
|
|
107
113
|
profileSource={
|
|
@@ -23,7 +23,7 @@ import {capitalizeOnlyFirstLetter, safeDecode, type NavigateFunction} from '@par
|
|
|
23
23
|
|
|
24
24
|
import {ProfileSelection, ProfileSelectionFromParams, SuffixParams} from '..';
|
|
25
25
|
import {QuerySelection, useProfileTypes} from '../ProfileSelector';
|
|
26
|
-
import {
|
|
26
|
+
import {useResetFlameGraphState} from '../ProfileView/hooks/useResetFlameGraphState';
|
|
27
27
|
import {useResetStateOnProfileTypeChange} from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
|
|
28
28
|
import {sumByToParam, useSumByFromParams} from '../useSumBy';
|
|
29
29
|
import ProfileExplorerCompare from './ProfileExplorerCompare';
|
|
@@ -162,7 +162,7 @@ const ProfileExplorerApp = ({
|
|
|
162
162
|
const [profileB, setProfileB] = useState<ProfileSelection | null>(null);
|
|
163
163
|
|
|
164
164
|
const resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
|
|
165
|
-
const
|
|
165
|
+
const resetFlameGraphState = useResetFlameGraphState();
|
|
166
166
|
|
|
167
167
|
const sumByA = useSumByFromParams(sum_by_a);
|
|
168
168
|
const sumByB = useSumByFromParams(sum_by_b);
|
|
@@ -250,7 +250,7 @@ const ProfileExplorerApp = ({
|
|
|
250
250
|
resetStateOnProfileTypeChange();
|
|
251
251
|
} else {
|
|
252
252
|
// Reset the state when a new search is performed.
|
|
253
|
-
|
|
253
|
+
resetFlameGraphState();
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
useURLState,
|
|
26
26
|
} from '@parca/components';
|
|
27
27
|
import {ProfileType} from '@parca/parser';
|
|
28
|
-
import {testId} from '@parca/test-utils';
|
|
28
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
29
29
|
import {capitalizeOnlyFirstLetter, divide} from '@parca/utilities';
|
|
30
30
|
|
|
31
31
|
import {MergedProfileSource, ProfileSource} from '../ProfileSource';
|
|
@@ -396,7 +396,7 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
|
|
|
396
396
|
<div
|
|
397
397
|
className={cx(!isInSandwichView ? 'min-h-48' : '')}
|
|
398
398
|
id="h-flame-graph"
|
|
399
|
-
{...testId(
|
|
399
|
+
{...testId(TEST_IDS.FLAMEGRAPH_CONTAINER)}
|
|
400
400
|
>
|
|
401
401
|
<>{flameGraph}</>
|
|
402
402
|
</div>
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
useParcaContext,
|
|
30
30
|
} from '@parca/components';
|
|
31
31
|
import {Query} from '@parca/parser';
|
|
32
|
-
import {testId} from '@parca/test-utils';
|
|
32
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
33
33
|
import {capitalizeOnlyFirstLetter, formatDate, timePattern, valueFormatter} from '@parca/utilities';
|
|
34
34
|
|
|
35
35
|
import {MergedProfileSelection, ProfileSelection} from '..';
|
|
@@ -491,7 +491,7 @@ const ProfileMetricsGraph = ({
|
|
|
491
491
|
<div
|
|
492
492
|
key={name}
|
|
493
493
|
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"
|
|
494
|
-
{...testId(
|
|
494
|
+
{...testId(TEST_IDS.TOOLTIP_LABEL)}
|
|
495
495
|
>
|
|
496
496
|
<TextWithTooltip
|
|
497
497
|
text={`${name.replace('attributes.', '')}="${
|
|
@@ -513,7 +513,7 @@ const ProfileMetricsGraph = ({
|
|
|
513
513
|
<div
|
|
514
514
|
key={name}
|
|
515
515
|
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"
|
|
516
|
-
{...testId(
|
|
516
|
+
{...testId(TEST_IDS.TOOLTIP_LABEL)}
|
|
517
517
|
>
|
|
518
518
|
<TextWithTooltip
|
|
519
519
|
text={`${name.replace('attributes.', '')}="${
|
|
@@ -534,7 +534,7 @@ const ProfileMetricsGraph = ({
|
|
|
534
534
|
<div
|
|
535
535
|
key={label.name}
|
|
536
536
|
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"
|
|
537
|
-
{...testId(
|
|
537
|
+
{...testId(TEST_IDS.TOOLTIP_LABEL)}
|
|
538
538
|
>
|
|
539
539
|
<TextWithTooltip
|
|
540
540
|
text={`${label.name}="${label.value}"`}
|
|
@@ -18,7 +18,7 @@ import Select, {type SelectInstance} from 'react-select';
|
|
|
18
18
|
import {ProfileTypesResponse, QueryServiceClient} from '@parca/client';
|
|
19
19
|
import {Button, DateTimeRange, DateTimeRangePicker, useParcaContext} from '@parca/components';
|
|
20
20
|
import {ProfileType, Query} from '@parca/parser';
|
|
21
|
-
import {testId} from '@parca/test-utils';
|
|
21
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
22
22
|
|
|
23
23
|
import MatchersInput from '../MatchersInput';
|
|
24
24
|
import ProfileTypeSelector from '../ProfileTypeSelector';
|
|
@@ -97,11 +97,11 @@ export function QueryControls({
|
|
|
97
97
|
return (
|
|
98
98
|
<div
|
|
99
99
|
className="flex w-full flex-wrap items-start gap-2"
|
|
100
|
-
{...testId(
|
|
100
|
+
{...testId(TEST_IDS.QUERY_CONTROLS_CONTAINER)}
|
|
101
101
|
>
|
|
102
102
|
{showProfileTypeSelector && (
|
|
103
103
|
<div>
|
|
104
|
-
<label className="text-xs" {...testId(
|
|
104
|
+
<label className="text-xs" {...testId(TEST_IDS.PROFILE_TYPE_LABEL)}>
|
|
105
105
|
Profile type
|
|
106
106
|
</label>
|
|
107
107
|
<ProfileTypeSelector
|
|
@@ -118,11 +118,11 @@ export function QueryControls({
|
|
|
118
118
|
<div
|
|
119
119
|
className="w-full flex-1 flex flex-col gap-1 mt-auto"
|
|
120
120
|
ref={queryBrowserRef}
|
|
121
|
-
{...testId(
|
|
121
|
+
{...testId(TEST_IDS.QUERY_BROWSER_CONTAINER)}
|
|
122
122
|
>
|
|
123
123
|
<div className="flex items-center justify-between">
|
|
124
124
|
<div className="flex items-center gap-3">
|
|
125
|
-
<label className="text-xs" {...testId(
|
|
125
|
+
<label className="text-xs" {...testId(TEST_IDS.QUERY_LABEL)}>
|
|
126
126
|
Query
|
|
127
127
|
</label>
|
|
128
128
|
{viewComponent?.disableExplorativeQuerying !== true && (
|
|
@@ -136,7 +136,7 @@ export function QueryControls({
|
|
|
136
136
|
className={`${
|
|
137
137
|
advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'
|
|
138
138
|
} 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`}
|
|
139
|
-
{...testId(
|
|
139
|
+
{...testId(TEST_IDS.ADVANCED_MODE_SWITCH)}
|
|
140
140
|
>
|
|
141
141
|
<span className="sr-only">Use setting</span>
|
|
142
142
|
<span
|
|
@@ -146,7 +146,7 @@ export function QueryControls({
|
|
|
146
146
|
} pointer-events-none inline-block h-[16px] w-[16px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out`}
|
|
147
147
|
/>
|
|
148
148
|
</Switch>
|
|
149
|
-
<label className="text-xs" {...testId(
|
|
149
|
+
<label className="text-xs" {...testId(TEST_IDS.QUERY_MODE_LABEL)}>
|
|
150
150
|
Advanced Mode
|
|
151
151
|
</label>
|
|
152
152
|
</>
|
|
@@ -194,15 +194,15 @@ export function QueryControls({
|
|
|
194
194
|
</div>
|
|
195
195
|
|
|
196
196
|
{showSumBySelector && (
|
|
197
|
-
<div {...testId(
|
|
197
|
+
<div {...testId(TEST_IDS.SUM_BY_CONTAINER)}>
|
|
198
198
|
<div className="mb-0.5 mt-1.5 flex items-center justify-between">
|
|
199
|
-
<label className="text-xs" {...testId(
|
|
199
|
+
<label className="text-xs" {...testId(TEST_IDS.SUM_BY_LABEL)}>
|
|
200
200
|
Sum by
|
|
201
201
|
</label>
|
|
202
202
|
</div>
|
|
203
203
|
<Select<SelectOption, true>
|
|
204
204
|
id="h-sum-by-selector"
|
|
205
|
-
data-testid={testId(
|
|
205
|
+
data-testid={testId(TEST_IDS.SUM_BY_SELECT)['data-testid']}
|
|
206
206
|
defaultValue={[]}
|
|
207
207
|
isMulti
|
|
208
208
|
isClearable={false}
|
|
@@ -250,11 +250,11 @@ export function QueryControls({
|
|
|
250
250
|
onRangeSelection={setTimeRangeSelection}
|
|
251
251
|
range={timeRangeSelection}
|
|
252
252
|
timezone={timezone}
|
|
253
|
-
{...testId(
|
|
253
|
+
{...testId(TEST_IDS.DATE_TIME_RANGE_PICKER)}
|
|
254
254
|
/>
|
|
255
255
|
|
|
256
256
|
<div>
|
|
257
|
-
<label className="text-xs" {...testId(
|
|
257
|
+
<label className="text-xs" {...testId(TEST_IDS.SEARCH_BUTTON_LABEL)}>
|
|
258
258
|
|
|
259
259
|
</label>
|
|
260
260
|
<Button
|
|
@@ -264,7 +264,7 @@ export function QueryControls({
|
|
|
264
264
|
setQueryExpression(true);
|
|
265
265
|
}}
|
|
266
266
|
id="h-matcher-search-button"
|
|
267
|
-
{...testId(
|
|
267
|
+
{...testId(TEST_IDS.SEARCH_BUTTON)}
|
|
268
268
|
>
|
|
269
269
|
Search
|
|
270
270
|
</Button>
|
|
@@ -17,7 +17,7 @@ import {RpcError} from '@protobuf-ts/runtime-rpc';
|
|
|
17
17
|
|
|
18
18
|
import {ProfileType, ProfileTypesResponse} from '@parca/client';
|
|
19
19
|
import {Select, type SelectElement} from '@parca/components';
|
|
20
|
-
import {testId} from '@parca/test-utils';
|
|
20
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
21
21
|
|
|
22
22
|
interface WellKnownProfile {
|
|
23
23
|
name: string;
|
|
@@ -198,7 +198,7 @@ const ProfileTypeSelector = ({
|
|
|
198
198
|
loading={loading}
|
|
199
199
|
className="bg-white h-profile-type-dropdown"
|
|
200
200
|
disabled={disabled}
|
|
201
|
-
{...testId(
|
|
201
|
+
{...testId(TEST_IDS.PROFILE_TYPE_SELECTOR)}
|
|
202
202
|
/>
|
|
203
203
|
);
|
|
204
204
|
};
|
|
@@ -42,8 +42,6 @@ interface GetDashboardItemProps {
|
|
|
42
42
|
profileSource: ProfileSource;
|
|
43
43
|
total: bigint;
|
|
44
44
|
filtered: bigint;
|
|
45
|
-
curPath: string[];
|
|
46
|
-
setNewCurPath: (path: string[]) => void;
|
|
47
45
|
curPathArrow: CurrentPathFrame[];
|
|
48
46
|
setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
|
|
49
47
|
perf?: {
|
|
@@ -17,7 +17,7 @@ import {Popover, Transition} from '@headlessui/react';
|
|
|
17
17
|
import {usePopper} from 'react-popper';
|
|
18
18
|
|
|
19
19
|
import {selectDarkMode, useAppSelector} from '@parca/store';
|
|
20
|
-
import {testId} from '@parca/test-utils';
|
|
20
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
21
21
|
import {getIncreasedSpanColor, getNewSpanColor, getReducedSpanColor} from '@parca/utilities';
|
|
22
22
|
|
|
23
23
|
const transparencyValues = [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100];
|
|
@@ -75,7 +75,7 @@ const DiffLegend = (): JSX.Element => {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
return (
|
|
78
|
-
<div className="mt-1 mb-2 hidden md:block" id="h-diff-legend" {...testId(
|
|
78
|
+
<div className="mt-1 mb-2 hidden md:block" id="h-diff-legend" {...testId(TEST_IDS.DIFF_LEGEND)}>
|
|
79
79
|
<div ref={setReferenceElement} className="flex items-center justify-center">
|
|
80
80
|
<span>Better</span>
|
|
81
81
|
<DiffLegendBar onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} />
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import Select from 'react-select';
|
|
15
15
|
|
|
16
|
-
import {testId} from '@parca/test-utils';
|
|
16
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
17
17
|
|
|
18
18
|
import {FIELD_LABELS} from '../../../ProfileFlameGraph/FlameGraphArrow';
|
|
19
19
|
|
|
@@ -30,9 +30,9 @@ interface Props {
|
|
|
30
30
|
|
|
31
31
|
const GroupByLabelsDropdown = ({labels, groupBy, setGroupByLabels}: Props): JSX.Element => {
|
|
32
32
|
return (
|
|
33
|
-
<div className="flex flex-col relative" {...testId(
|
|
33
|
+
<div className="flex flex-col relative" {...testId(TEST_IDS.GROUP_BY_CONTAINER)}>
|
|
34
34
|
<div className="flex items-center justify-between">
|
|
35
|
-
<label className="text-sm" {...testId(
|
|
35
|
+
<label className="text-sm" {...testId(TEST_IDS.GROUP_BY_LABEL)}>
|
|
36
36
|
Group by
|
|
37
37
|
</label>
|
|
38
38
|
</div>
|
|
@@ -50,7 +50,7 @@ const GroupByLabelsDropdown = ({labels, groupBy, setGroupByLabels}: Props): JSX.
|
|
|
50
50
|
MenuList: ({children, innerProps}) => (
|
|
51
51
|
<div
|
|
52
52
|
className="overflow-y-auto"
|
|
53
|
-
{...testId(
|
|
53
|
+
{...testId(TEST_IDS.GROUP_BY_SELECT_FLYOUT)}
|
|
54
54
|
{...innerProps}
|
|
55
55
|
// eslint-disable-next-line react/prop-types
|
|
56
56
|
style={{...innerProps.style, height: '332px', maxHeight: '332px', fontSize: '14px'}}
|
|
@@ -17,7 +17,7 @@ import {Icon} from '@iconify/react';
|
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
|
|
19
19
|
import {Button, Input, Select, type SelectItem} from '@parca/components';
|
|
20
|
-
import {testId} from '@parca/test-utils';
|
|
20
|
+
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
21
21
|
|
|
22
22
|
import {useProfileViewContext} from '../../context/ProfileViewContext';
|
|
23
23
|
import {getPresetByKey, getPresetsForProfileType, isPresetKey} from './filterPresets';
|
|
@@ -205,7 +205,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
205
205
|
const filtersToRender = localFilters.length > 0 ? localFilters : appliedFilters ?? [];
|
|
206
206
|
|
|
207
207
|
return (
|
|
208
|
-
<div className="flex gap-2 w-full items-start" {...testId(
|
|
208
|
+
<div className="flex gap-2 w-full items-start" {...testId(TEST_IDS.PROFILE_FILTERS_CONTAINER)}>
|
|
209
209
|
<div className="flex-1 flex flex-wrap gap-2">
|
|
210
210
|
{filtersToRender.map(filter => {
|
|
211
211
|
const isNumberField = filter.field === 'address' || filter.field === 'line_number';
|
|
@@ -219,7 +219,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
219
219
|
selectedKey={filter.type}
|
|
220
220
|
placeholder="Select Filter"
|
|
221
221
|
disabled={readOnly}
|
|
222
|
-
{...testId(
|
|
222
|
+
{...testId(TEST_IDS.FILTER_TYPE_SELECT)}
|
|
223
223
|
flyoutTestId="filter-type-select-flyout"
|
|
224
224
|
onSelection={key => {
|
|
225
225
|
// Check if this is a preset selection
|
|
@@ -269,7 +269,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
269
269
|
items={fieldItems}
|
|
270
270
|
selectedKey={filter.field ?? ''}
|
|
271
271
|
disabled={readOnly}
|
|
272
|
-
{...testId(
|
|
272
|
+
{...testId(TEST_IDS.FILTER_FIELD_SELECT)}
|
|
273
273
|
flyoutTestId="filter-field-select-flyout"
|
|
274
274
|
onSelection={key => {
|
|
275
275
|
const newField = key as ProfileFilter['field'];
|
|
@@ -297,7 +297,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
297
297
|
items={matchTypeItems}
|
|
298
298
|
selectedKey={filter.matchType ?? ''}
|
|
299
299
|
disabled={readOnly}
|
|
300
|
-
{...testId(
|
|
300
|
+
{...testId(TEST_IDS.FILTER_MATCH_TYPE_SELECT)}
|
|
301
301
|
flyoutTestId="filter-match-type-select-flyout"
|
|
302
302
|
onSelection={key =>
|
|
303
303
|
updateFilter(filter.id, {matchType: key as ProfileFilter['matchType']})
|
|
@@ -316,7 +316,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
316
316
|
onChange={e => updateFilter(filter.id, {value: e.target.value})}
|
|
317
317
|
onKeyDown={handleKeyDown}
|
|
318
318
|
className="rounded-none w-36 text-sm focus:outline-1"
|
|
319
|
-
{...testId(
|
|
319
|
+
{...testId(TEST_IDS.FILTER_VALUE_INPUT)}
|
|
320
320
|
/>
|
|
321
321
|
</>
|
|
322
322
|
)}
|
|
@@ -324,7 +324,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
324
324
|
{!readOnly && (
|
|
325
325
|
<Button
|
|
326
326
|
variant="neutral"
|
|
327
|
-
{...testId(
|
|
327
|
+
{...testId(TEST_IDS.FILTER_REMOVE_BUTTON)}
|
|
328
328
|
onClick={() => {
|
|
329
329
|
// If we're displaying local filters and this is the last one, reset everything
|
|
330
330
|
if (localFilters.length > 0 && localFilters.length === 1) {
|
|
@@ -358,7 +358,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
358
358
|
variant="neutral"
|
|
359
359
|
onClick={addFilter}
|
|
360
360
|
className="p-3 h-[38px]"
|
|
361
|
-
{...testId(
|
|
361
|
+
{...testId(TEST_IDS.ADD_FILTER_BUTTON)}
|
|
362
362
|
>
|
|
363
363
|
<Icon icon="mdi:filter-plus-outline" className="h-4 w-4" />
|
|
364
364
|
</Button>
|
|
@@ -369,7 +369,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
369
369
|
variant="neutral"
|
|
370
370
|
onClick={addFilter}
|
|
371
371
|
className="flex items-center gap-2"
|
|
372
|
-
{...testId(
|
|
372
|
+
{...testId(TEST_IDS.ADD_FILTER_BUTTON)}
|
|
373
373
|
>
|
|
374
374
|
<Icon icon="mdi:filter-outline" className="h-4 w-4" />
|
|
375
375
|
<span>Filter</span>
|
|
@@ -383,7 +383,7 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
383
383
|
onClick={onApplyFilters}
|
|
384
384
|
disabled={!hasUnsavedChanges || !localFilters.some(isFilterComplete)}
|
|
385
385
|
className={cx('flex items-center gap-2 sticky top-0')}
|
|
386
|
-
{...testId(
|
|
386
|
+
{...testId(TEST_IDS.APPLY_FILTERS_BUTTON)}
|
|
387
387
|
>
|
|
388
388
|
<span>Apply</span>
|
|
389
389
|
</Button>
|