@parca/profile 0.19.36 → 0.19.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/MatchersInput/index.d.ts.map +1 -1
- package/dist/MatchersInput/index.js +3 -2
- package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/index.js +2 -1
- package/dist/ProfileSelector/QueryControls.d.ts.map +1 -1
- package/dist/ProfileSelector/QueryControls.js +6 -5
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +2 -1
- package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/index.js +2 -1
- package/dist/SimpleMatchers/index.d.ts.map +1 -1
- package/dist/SimpleMatchers/index.js +3 -2
- package/dist/ViewMatchers/index.d.ts.map +1 -1
- package/dist/ViewMatchers/index.js +2 -1
- package/package.json +4 -3
- package/src/MatchersInput/index.tsx +6 -1
- package/src/ProfileFlameGraph/index.tsx +6 -1
- package/src/ProfileSelector/QueryControls.tsx +34 -9
- package/src/ProfileTypeSelector/index.tsx +2 -0
- package/src/ProfileView/components/Toolbars/index.tsx +2 -0
- package/src/SimpleMatchers/index.tsx +9 -1
- package/src/ViewMatchers/index.tsx +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
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.37](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.36...@parca/profile@0.19.37) (2025-08-21)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## [0.19.36](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.35...@parca/profile@0.19.36) (2025-08-15)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAgB,cAAc,EAAE,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAE/F,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAgB,cAAc,EAAE,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAE/F,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAIpC,OAAO,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAKrD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,aAAa,GACxB,QAAQ,kBAAkB,EAC1B,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,QAAQ,MAAM,EAAE,KACf,aAyBF,CAAC;AAEF,UAAU,cAAc;IACtB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,EAAE,KAAK,CAAC;KACf,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,cAAc,GACzB,QAAQ,kBAAkB,EAC1B,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,cA0BF,CAAC;AAEF,eAAO,MAAM,8BAA8B,GACzC,WAAW,MAAM,EACjB,oBAAoB,iBAAiB,KACpC,MAAM,EASR,CAAC;AAqMF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAWxF"}
|
|
@@ -17,6 +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
21
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
21
22
|
import { LabelsProvider, useLabels } from '../contexts/MatchersInputLabelsContext';
|
|
22
23
|
import useGrpcQuery from '../useGrpcQuery';
|
|
@@ -193,9 +194,9 @@ const MatchersInput = ({ setMatchersString, runQuery, currentQuery, }) => {
|
|
|
193
194
|
setFocusedInput(false);
|
|
194
195
|
};
|
|
195
196
|
const profileSelected = currentQuery.profileName() === '';
|
|
196
|
-
return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", 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
|
|
197
|
+
return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", ...testId('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
|
|
197
198
|
? 'Select a profile first to enter a filter...'
|
|
198
|
-
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, onFocus: focus, disabled: profileSelected, title: profileSelected
|
|
199
|
+
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId('MATCHERS_TEXTAREA'), onFocus: focus, disabled: profileSelected, title: profileSelected
|
|
199
200
|
? 'Select a profile first to enter a filter...'
|
|
200
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 })] }));
|
|
201
202
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAM7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAO9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAM7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAO9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAMpE,OAAO,EAAC,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AAIlF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAUD,eAAO,MAAM,uBAAuB,GAClC,eAAe,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAIpE,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAqC,oPAmBzD,sBAAsB,KAAG,GAAG,CAAC,OAkT/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -16,6 +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
20
|
import { capitalizeOnlyFirstLetter, divide } from '@parca/utilities';
|
|
20
21
|
import DiffLegend from '../ProfileView/components/DiffLegend';
|
|
21
22
|
import { useProfileViewContext } from '../ProfileView/context/ProfileViewContext';
|
|
@@ -162,6 +163,6 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
|
|
|
162
163
|
}
|
|
163
164
|
return (_jsx(ErrorContent, { errorMessage: _jsxs(_Fragment, { children: [_jsx("span", { children: capitalizeOnlyFirstLetter(error.message) }), isFlameChart ? flamechartHelpText ?? null : null] }) }));
|
|
164
165
|
}
|
|
165
|
-
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", 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") }));
|
|
166
|
+
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('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") }));
|
|
166
167
|
};
|
|
167
168
|
export default ProfileFlameGraph;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryControls.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/QueryControls.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAClD,OAAe,EAAC,KAAK,cAAc,EAAC,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAC,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACvE,OAAO,EAAS,aAAa,EAAsB,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAC,WAAW,EAAE,KAAK,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"QueryControls.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/QueryControls.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAClD,OAAe,EAAC,KAAK,cAAc,EAAC,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAC,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACvE,OAAO,EAAS,aAAa,EAAsB,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAC,WAAW,EAAE,KAAK,EAAC,MAAM,eAAe,CAAC;AAajD,UAAU,kBAAkB;IAC1B,uBAAuB,EAAE,OAAO,CAAC;IACjC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,0BAA0B,EAAE,OAAO,CAAC;IACpC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACnD,iBAAiB,CAAC,EAAE,QAAQ,CAAC;IAC7B,aAAa,CAAC,EAAE;QACd,2BAA2B,CAAC,EAAE,OAAO,CAAC;QACtC,0BAA0B,CAAC,EAAE,OAAO,CAAC;QACrC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;KACvC,CAAC;IACF,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,2BAA2B,EAAE,OAAO,CAAC;IACrC,8BAA8B,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACjD,kBAAkB,EAAE,aAAa,CAAC;IAClC,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qBAAqB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC1C,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,uBAAuB,EACvB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,2BAA2B,EAC3B,8BAA8B,EAC9B,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,WAAW,EACX,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,iBAAiB,GAClB,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAiLlC"}
|
|
@@ -14,17 +14,18 @@ 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 } from '@parca/components';
|
|
17
|
+
import { testId } from '@parca/test-utils';
|
|
17
18
|
import MatchersInput from '../MatchersInput';
|
|
18
19
|
import ProfileTypeSelector from '../ProfileTypeSelector';
|
|
19
20
|
import SimpleMatchers from '../SimpleMatchers';
|
|
20
21
|
import ViewMatchers from '../ViewMatchers';
|
|
21
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, }) {
|
|
22
|
-
return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", children: [showProfileTypeSelector && (_jsxs("div", { children: [_jsx("label", { className: "text-xs", 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, children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("label", { className: "text-xs", children: "Query" }), viewComponent?.disableExplorativeQuerying !== true && (_jsxs(_Fragment, { children: [_jsxs(Switch, { checked: advancedModeForQueryBrowser, onChange: () => {
|
|
23
|
+
return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", ...testId('QUERY_CONTROLS_CONTAINER'), children: [showProfileTypeSelector && (_jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId('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('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('QUERY_LABEL'), children: "Query" }), viewComponent?.disableExplorativeQuerying !== true && (_jsxs(_Fragment, { children: [_jsxs(Switch, { checked: advancedModeForQueryBrowser, onChange: () => {
|
|
23
24
|
setAdvancedModeForQueryBrowser(!advancedModeForQueryBrowser);
|
|
24
25
|
setQueryBrowserMode(advancedModeForQueryBrowser ? 'simple' : 'advanced');
|
|
25
|
-
}, 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`, 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", children: "Advanced Mode" })] }))] }), viewComponent?.createViewComponent] }), viewComponent?.disableExplorativeQuerying === true &&
|
|
26
|
+
}, 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('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('QUERY_MODE_LABEL'), children: "Advanced Mode" })] }))] }), viewComponent?.createViewComponent] }), viewComponent?.disableExplorativeQuerying === true &&
|
|
26
27
|
viewComponent?.labelnames !== undefined &&
|
|
27
|
-
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", { children: [_jsx("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: _jsx("label", { className: "text-xs", children: "Sum by" }) }), _jsx(Select, { id: "h-sum-by-selector", 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 => {
|
|
28
|
+
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('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('SUM_BY_LABEL'), children: "Sum by" }) }), _jsx(Select, { id: "h-sum-by-selector", "data-testid": testId('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 => {
|
|
28
29
|
setUserSumBySelection(newValue.map(option => option.value));
|
|
29
30
|
}, placeholder: "Labels...", styles: {
|
|
30
31
|
indicatorSeparator: () => ({ display: 'none' }),
|
|
@@ -47,8 +48,8 @@ export function QueryControls({ showProfileTypeSelector, profileTypesData, profi
|
|
|
47
48
|
setQueryExpression(true);
|
|
48
49
|
currentRef.blur();
|
|
49
50
|
}
|
|
50
|
-
} })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsxs("div", { children: [_jsx("label", { className: "text-xs", children: "\u00A0" }), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
|
|
51
|
+
} })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection, ...testId('DATE_TIME_RANGE_PICKER') }), _jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId('SEARCH_BUTTON_LABEL'), children: "\u00A0" }), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
|
|
51
52
|
e.preventDefault();
|
|
52
53
|
setQueryExpression(true);
|
|
53
|
-
}, id: "h-matcher-search-button", children: "Search" })] })] }));
|
|
54
|
+
}, id: "h-matcher-search-button", ...testId('SEARCH_BUTTON'), children: "Search" })] })] }));
|
|
54
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAG7D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,iBAiF/B,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAU3F;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,8BAA8B,EAAE,OAAO,GACtC,aAAa,CAiBf;AAED,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,WAAW,EAAE,KAAG,MAAM,EAItE,CAAC;AAEF,UAAU,KAAK;IACb,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,mBAAmB,GAAI,2GAQ1B,KAAK,KAAG,GAAG,CAAC,OA0Bd,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -13,6 +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
17
|
export const wellKnownProfiles = {
|
|
17
18
|
'block:contentions:count:contentions:count': {
|
|
18
19
|
name: 'Block Contentions Total',
|
|
@@ -138,6 +139,6 @@ const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selecte
|
|
|
138
139
|
key: name,
|
|
139
140
|
element: profileSelectElement(name, flexibleKnownProfilesDetection),
|
|
140
141
|
}));
|
|
141
|
-
return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled }));
|
|
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('PROFILE_TYPE_SELECTOR') }));
|
|
142
143
|
};
|
|
143
144
|
export default ProfileTypeSelector;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/Toolbars/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAIzB,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/Toolbars/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAIzB,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAUrD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,aAAa,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6BAA6B,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,aAAa,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,8BAA8B;IAC7C,yBAAyB,EAAE,MAAM,IAAI,CAAC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAQ9C,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAkBxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,8BAA8B,CAmBxE,CAAC;AAMF,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,yBAAyB,CAyF9D,CAAC"}
|
|
@@ -1,6 +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
5
|
import { useDashboard } from '../../context/DashboardContext';
|
|
5
6
|
import GroupByDropdown from '../ActionButtons/GroupByDropdown';
|
|
6
7
|
import InvertCallStack from '../InvertCallStack';
|
|
@@ -13,7 +14,7 @@ export const TableToolbar = ({ profileType, total, filtered }) => {
|
|
|
13
14
|
return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsx(TableColumnsDropdown, { profileType: profileType, total: total, filtered: filtered }) }) }));
|
|
14
15
|
};
|
|
15
16
|
export const FlameGraphToolbar = ({ curPath, setNewCurPath }) => {
|
|
16
|
-
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", children: ["Reset graph", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }) }) }));
|
|
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('FLAMEGRAPH_RESET_BUTTON'), children: ["Reset graph", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }) }) }));
|
|
17
18
|
};
|
|
18
19
|
export const SandwichFlameGraphToolbar = ({ resetSandwichFunctionName, sandwichFunctionName, }) => {
|
|
19
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" }) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAMpC,OAAe,EAAC,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAEjD,UAAU,KAAK;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAoBD,eAAO,MAAM,wBAAwB,GAAI,YAAY,MAAM,EAAE,KAAG,UAAU,EAQzE,CAAC;AA2WF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAoB3E"}
|
|
@@ -16,6 +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
20
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
20
21
|
import { LabelProvider, useLabels } from '../contexts/SimpleMatchersLabelContext';
|
|
21
22
|
import { useUtilizationLabels } from '../contexts/UtilizationLabelsContext';
|
|
@@ -241,9 +242,9 @@ const SimpleMatchers = ({ queryClient, setMatchersString, currentQuery, profileT
|
|
|
241
242
|
};
|
|
242
243
|
}, [queryRows, fetchLabelValuesUnified]);
|
|
243
244
|
const isRowRegex = (row) => row.operator === '=~' || row.operator === '!~';
|
|
244
|
-
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", children: [visibleRows.map((row, index) => (_jsxs("div", { className: "flex items-center", 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 }), _jsx(Select, { items: operatorOptions, onSelection: value => handleUpdateRow(index, 'operator', value), selectedKey: row.operator, className: "rounded-none ring-0 focus:ring-0 outline-none" }), _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]', {
|
|
245
|
+
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", ...testId('SIMPLE_MATCHERS_CONTAINER'), children: [visibleRows.map((row, index) => (_jsxs("div", { className: "flex items-center", ...testId('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('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('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]', {
|
|
245
246
|
'w-[300px]': isRowRegex(row),
|
|
246
|
-
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row) }), _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'), 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", 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", children: _jsx(Icon, { icon: "material-symbols:add", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) })] }));
|
|
247
|
+
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row), ...testId('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('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 ? 'SHOW_LESS_BUTTON' : '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('ADD_MATCHER_BUTTON'), children: _jsx(Icon, { icon: "material-symbols:add", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) })] }));
|
|
247
248
|
};
|
|
248
249
|
export default function SimpleMathersWithProvider(props) {
|
|
249
250
|
const labelNameFromMatchers = useMemo(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ViewMatchers/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAKtE,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ViewMatchers/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAKtE,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAMpC,UAAU,KAAK;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAqKjC,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -15,6 +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
19
|
import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
|
|
19
20
|
import CustomSelect from '../SimpleMatchers/Select';
|
|
20
21
|
const ViewMatchers = ({ labelNames, profileType, queryClient, runQuery, setMatchersString, start, end, currentQuery, }) => {
|
|
@@ -108,6 +109,6 @@ const ViewMatchers = ({ labelNames, profileType, queryClient, runQuery, setMatch
|
|
|
108
109
|
element: { active: _jsx(_Fragment, { children: value }), expanded: _jsx(_Fragment, { children: value }) },
|
|
109
110
|
}));
|
|
110
111
|
}, []);
|
|
111
|
-
return (_jsx("div", { className: "flex flex-wrap gap-2", 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))) }));
|
|
112
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2", ...testId('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))) }));
|
|
112
113
|
};
|
|
113
114
|
export default ViewMatchers;
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.37",
|
|
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.3",
|
|
10
|
-
"@parca/components": "0.16.
|
|
10
|
+
"@parca/components": "0.16.358",
|
|
11
11
|
"@parca/dynamicsize": "0.16.65",
|
|
12
12
|
"@parca/hooks": "0.0.99",
|
|
13
13
|
"@parca/icons": "0.16.72",
|
|
14
14
|
"@parca/parser": "0.16.79",
|
|
15
15
|
"@parca/store": "0.16.183",
|
|
16
|
+
"@parca/test-utils": "0.0.2",
|
|
16
17
|
"@parca/utilities": "0.0.106",
|
|
17
18
|
"@popperjs/core": "^2.11.8",
|
|
18
19
|
"@protobuf-ts/runtime-rpc": "^2.5.0",
|
|
@@ -78,5 +79,5 @@
|
|
|
78
79
|
"access": "public",
|
|
79
80
|
"registry": "https://registry.npmjs.org/"
|
|
80
81
|
},
|
|
81
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "7a6143408ac1e4108e8bfe4725f67f4650b613d4"
|
|
82
83
|
}
|
|
@@ -20,6 +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
24
|
import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
|
|
24
25
|
|
|
25
26
|
import {UtilizationLabels} from '../ProfileSelector';
|
|
@@ -289,7 +290,10 @@ const MatchersInput = ({
|
|
|
289
290
|
const profileSelected = currentQuery.profileName() === '';
|
|
290
291
|
|
|
291
292
|
return (
|
|
292
|
-
<div
|
|
293
|
+
<div
|
|
294
|
+
className="w-full min-w-[300px] flex-1 font-mono relative"
|
|
295
|
+
{...testId('MATCHERS_INPUT_CONTAINER')}
|
|
296
|
+
>
|
|
293
297
|
<TextareaAutosize
|
|
294
298
|
ref={inputRef}
|
|
295
299
|
className={cx(
|
|
@@ -304,6 +308,7 @@ const MatchersInput = ({
|
|
|
304
308
|
onChange={onChange}
|
|
305
309
|
value={value}
|
|
306
310
|
onBlur={unfocus}
|
|
311
|
+
{...testId('MATCHERS_TEXTAREA')}
|
|
307
312
|
onFocus={focus}
|
|
308
313
|
disabled={profileSelected} // Disable input if no profile has been selected
|
|
309
314
|
title={
|
|
@@ -25,6 +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
29
|
import {capitalizeOnlyFirstLetter, divide} from '@parca/utilities';
|
|
29
30
|
|
|
30
31
|
import {MergedProfileSource, ProfileSource} from '../ProfileSource';
|
|
@@ -380,7 +381,11 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
|
|
|
380
381
|
transition={{duration: 0.5}}
|
|
381
382
|
>
|
|
382
383
|
{compareMode ? <DiffLegend /> : null}
|
|
383
|
-
<div
|
|
384
|
+
<div
|
|
385
|
+
className={cx(!isInSandwichView ? 'min-h-48' : '')}
|
|
386
|
+
id="h-flame-graph"
|
|
387
|
+
{...testId('FLAMEGRAPH_CONTAINER')}
|
|
388
|
+
>
|
|
384
389
|
<>{flameGraph}</>
|
|
385
390
|
</div>
|
|
386
391
|
{!isInSandwichView && (
|
|
@@ -18,6 +18,7 @@ import Select, {type SelectInstance} from 'react-select';
|
|
|
18
18
|
import {ProfileTypesResponse, QueryServiceClient} from '@parca/client';
|
|
19
19
|
import {Button, DateTimeRange, DateTimeRangePicker} from '@parca/components';
|
|
20
20
|
import {ProfileType, Query} from '@parca/parser';
|
|
21
|
+
import {testId} from '@parca/test-utils';
|
|
21
22
|
|
|
22
23
|
import MatchersInput from '../MatchersInput';
|
|
23
24
|
import ProfileTypeSelector from '../ProfileTypeSelector';
|
|
@@ -92,10 +93,15 @@ export function QueryControls({
|
|
|
92
93
|
profileTypesError,
|
|
93
94
|
}: QueryControlsProps): JSX.Element {
|
|
94
95
|
return (
|
|
95
|
-
<div
|
|
96
|
+
<div
|
|
97
|
+
className="flex w-full flex-wrap items-start gap-2"
|
|
98
|
+
{...testId('QUERY_CONTROLS_CONTAINER')}
|
|
99
|
+
>
|
|
96
100
|
{showProfileTypeSelector && (
|
|
97
101
|
<div>
|
|
98
|
-
<label className="text-xs"
|
|
102
|
+
<label className="text-xs" {...testId('PROFILE_TYPE_LABEL')}>
|
|
103
|
+
Profile type
|
|
104
|
+
</label>
|
|
99
105
|
<ProfileTypeSelector
|
|
100
106
|
profileTypesData={profileTypesData}
|
|
101
107
|
loading={profileTypesLoading}
|
|
@@ -107,10 +113,16 @@ export function QueryControls({
|
|
|
107
113
|
</div>
|
|
108
114
|
)}
|
|
109
115
|
|
|
110
|
-
<div
|
|
116
|
+
<div
|
|
117
|
+
className="w-full flex-1 flex flex-col gap-1 mt-auto"
|
|
118
|
+
ref={queryBrowserRef}
|
|
119
|
+
{...testId('QUERY_BROWSER_CONTAINER')}
|
|
120
|
+
>
|
|
111
121
|
<div className="flex items-center justify-between">
|
|
112
122
|
<div className="flex items-center gap-3">
|
|
113
|
-
<label className="text-xs">
|
|
123
|
+
<label className="text-xs" {...testId('QUERY_LABEL')}>
|
|
124
|
+
Query
|
|
125
|
+
</label>
|
|
114
126
|
{viewComponent?.disableExplorativeQuerying !== true && (
|
|
115
127
|
<>
|
|
116
128
|
<Switch
|
|
@@ -122,6 +134,7 @@ export function QueryControls({
|
|
|
122
134
|
className={`${
|
|
123
135
|
advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'
|
|
124
136
|
} 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`}
|
|
137
|
+
{...testId('ADVANCED_MODE_SWITCH')}
|
|
125
138
|
>
|
|
126
139
|
<span className="sr-only">Use setting</span>
|
|
127
140
|
<span
|
|
@@ -131,7 +144,9 @@ export function QueryControls({
|
|
|
131
144
|
} pointer-events-none inline-block h-[16px] w-[16px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out`}
|
|
132
145
|
/>
|
|
133
146
|
</Switch>
|
|
134
|
-
<label className="text-xs"
|
|
147
|
+
<label className="text-xs" {...testId('QUERY_MODE_LABEL')}>
|
|
148
|
+
Advanced Mode
|
|
149
|
+
</label>
|
|
135
150
|
</>
|
|
136
151
|
)}
|
|
137
152
|
</div>
|
|
@@ -177,12 +192,15 @@ export function QueryControls({
|
|
|
177
192
|
</div>
|
|
178
193
|
|
|
179
194
|
{showSumBySelector && (
|
|
180
|
-
<div>
|
|
195
|
+
<div {...testId('SUM_BY_CONTAINER')}>
|
|
181
196
|
<div className="mb-0.5 mt-1.5 flex items-center justify-between">
|
|
182
|
-
<label className="text-xs"
|
|
197
|
+
<label className="text-xs" {...testId('SUM_BY_LABEL')}>
|
|
198
|
+
Sum by
|
|
199
|
+
</label>
|
|
183
200
|
</div>
|
|
184
201
|
<Select<SelectOption, true>
|
|
185
202
|
id="h-sum-by-selector"
|
|
203
|
+
data-testid={testId('SUM_BY_SELECT')['data-testid']}
|
|
186
204
|
defaultValue={[]}
|
|
187
205
|
isMulti
|
|
188
206
|
isClearable={false}
|
|
@@ -226,10 +244,16 @@ export function QueryControls({
|
|
|
226
244
|
</div>
|
|
227
245
|
)}
|
|
228
246
|
|
|
229
|
-
<DateTimeRangePicker
|
|
247
|
+
<DateTimeRangePicker
|
|
248
|
+
onRangeSelection={setTimeRangeSelection}
|
|
249
|
+
range={timeRangeSelection}
|
|
250
|
+
{...testId('DATE_TIME_RANGE_PICKER')}
|
|
251
|
+
/>
|
|
230
252
|
|
|
231
253
|
<div>
|
|
232
|
-
<label className="text-xs"
|
|
254
|
+
<label className="text-xs" {...testId('SEARCH_BUTTON_LABEL')}>
|
|
255
|
+
|
|
256
|
+
</label>
|
|
233
257
|
<Button
|
|
234
258
|
disabled={searchDisabled}
|
|
235
259
|
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
|
@@ -237,6 +261,7 @@ export function QueryControls({
|
|
|
237
261
|
setQueryExpression(true);
|
|
238
262
|
}}
|
|
239
263
|
id="h-matcher-search-button"
|
|
264
|
+
{...testId('SEARCH_BUTTON')}
|
|
240
265
|
>
|
|
241
266
|
Search
|
|
242
267
|
</Button>
|
|
@@ -17,6 +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
21
|
|
|
21
22
|
interface WellKnownProfile {
|
|
22
23
|
name: string;
|
|
@@ -197,6 +198,7 @@ const ProfileTypeSelector = ({
|
|
|
197
198
|
loading={loading}
|
|
198
199
|
className="bg-white h-profile-type-dropdown"
|
|
199
200
|
disabled={disabled}
|
|
201
|
+
{...testId('PROFILE_TYPE_SELECTOR')}
|
|
200
202
|
/>
|
|
201
203
|
);
|
|
202
204
|
};
|
|
@@ -18,6 +18,7 @@ import {Icon} from '@iconify/react';
|
|
|
18
18
|
import {QueryServiceClient} from '@parca/client';
|
|
19
19
|
import {Button} from '@parca/components';
|
|
20
20
|
import {ProfileType} from '@parca/parser';
|
|
21
|
+
import {testId} from '@parca/test-utils';
|
|
21
22
|
|
|
22
23
|
import {CurrentPathFrame} from '../../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
23
24
|
import {ProfileSource} from '../../../ProfileSource';
|
|
@@ -87,6 +88,7 @@ export const FlameGraphToolbar: FC<FlameGraphToolbarProps> = ({curPath, setNewCu
|
|
|
87
88
|
onClick={() => setNewCurPath([])}
|
|
88
89
|
disabled={curPath.length === 0}
|
|
89
90
|
id="h-reset-graph"
|
|
91
|
+
{...testId('FLAMEGRAPH_RESET_BUTTON')}
|
|
90
92
|
>
|
|
91
93
|
Reset graph
|
|
92
94
|
<Icon icon="system-uicons:reset" width={20} />
|
|
@@ -20,6 +20,7 @@ import cx from 'classnames';
|
|
|
20
20
|
import {QueryServiceClient} 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
24
|
import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
|
|
24
25
|
|
|
25
26
|
import {LabelProvider, useLabels} from '../contexts/SimpleMatchersLabelContext';
|
|
@@ -356,9 +357,10 @@ const SimpleMatchers = ({
|
|
|
356
357
|
<div
|
|
357
358
|
className={`flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`}
|
|
358
359
|
id="simple-matchers"
|
|
360
|
+
{...testId('SIMPLE_MATCHERS_CONTAINER')}
|
|
359
361
|
>
|
|
360
362
|
{visibleRows.map((row, index) => (
|
|
361
|
-
<div key={index} className="flex items-center">
|
|
363
|
+
<div key={index} className="flex items-center" {...testId('SIMPLE_MATCHER_ROW')}>
|
|
362
364
|
<Select
|
|
363
365
|
items={labelNameOptions}
|
|
364
366
|
onSelection={value => handleUpdateRow(index, 'labelName', value)}
|
|
@@ -367,12 +369,14 @@ const SimpleMatchers = ({
|
|
|
367
369
|
className="rounded-tr-none rounded-br-none ring-0 focus:ring-0 outline-none"
|
|
368
370
|
loading={labelNamesLoading}
|
|
369
371
|
searchable={true}
|
|
372
|
+
{...testId('LABEL_NAME_SELECT')}
|
|
370
373
|
/>
|
|
371
374
|
<Select
|
|
372
375
|
items={operatorOptions}
|
|
373
376
|
onSelection={value => handleUpdateRow(index, 'operator', value)}
|
|
374
377
|
selectedKey={row.operator}
|
|
375
378
|
className="rounded-none ring-0 focus:ring-0 outline-none"
|
|
379
|
+
{...testId('OPERATOR_SELECT')}
|
|
376
380
|
/>
|
|
377
381
|
<Select
|
|
378
382
|
items={transformLabelsForSelect(row.labelValues)}
|
|
@@ -388,12 +392,14 @@ const SimpleMatchers = ({
|
|
|
388
392
|
loading={row.isLoading}
|
|
389
393
|
onButtonClick={() => handleLabelValueClick(index)}
|
|
390
394
|
editable={isRowRegex(row)}
|
|
395
|
+
{...testId('LABEL_VALUE_SELECT')}
|
|
391
396
|
/>
|
|
392
397
|
<button
|
|
393
398
|
onClick={() => removeRow(index)}
|
|
394
399
|
className={cx(
|
|
395
400
|
'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'
|
|
396
401
|
)}
|
|
402
|
+
{...testId('REMOVE_MATCHER_BUTTON')}
|
|
397
403
|
>
|
|
398
404
|
<Icon icon="carbon:close" className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
|
399
405
|
</button>
|
|
@@ -404,6 +410,7 @@ const SimpleMatchers = ({
|
|
|
404
410
|
<button
|
|
405
411
|
onClick={() => setShowAll(!showAll)}
|
|
406
412
|
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"
|
|
413
|
+
{...testId(showAll ? 'SHOW_LESS_BUTTON' : 'SHOW_MORE_BUTTON')}
|
|
407
414
|
>
|
|
408
415
|
{showAll ? 'Show less' : `Show ${hiddenRowsCount} more`}
|
|
409
416
|
</button>
|
|
@@ -412,6 +419,7 @@ const SimpleMatchers = ({
|
|
|
412
419
|
<button
|
|
413
420
|
onClick={addNewRow}
|
|
414
421
|
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"
|
|
422
|
+
{...testId('ADD_MATCHER_BUTTON')}
|
|
415
423
|
>
|
|
416
424
|
<Icon icon="material-symbols:add" className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
|
417
425
|
</button>
|
|
@@ -19,6 +19,7 @@ import cx from 'classnames';
|
|
|
19
19
|
import {QueryServiceClient} from '@parca/client';
|
|
20
20
|
import {useGrpcMetadata} from '@parca/components';
|
|
21
21
|
import {Query} from '@parca/parser';
|
|
22
|
+
import {testId} from '@parca/test-utils';
|
|
22
23
|
import {millisToProtoTimestamp, sanitizeLabelValue} from '@parca/utilities';
|
|
23
24
|
|
|
24
25
|
import CustomSelect, {SelectItem} from '../SimpleMatchers/Select';
|
|
@@ -168,7 +169,7 @@ const ViewMatchers: React.FC<Props> = ({
|
|
|
168
169
|
}, []);
|
|
169
170
|
|
|
170
171
|
return (
|
|
171
|
-
<div className="flex flex-wrap gap-2">
|
|
172
|
+
<div className="flex flex-wrap gap-2" {...testId('VIEW_MATCHERS_CONTAINER')}>
|
|
172
173
|
{labelNames.map(labelName => (
|
|
173
174
|
<div key={labelName} className="flex items-center">
|
|
174
175
|
<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">
|