@parca/profile 0.16.390 → 0.16.392
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +1 -1
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +1 -2
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +2 -2
- package/dist/ProfileExplorer/index.d.ts +1 -0
- package/dist/ProfileExplorer/index.js +2 -27
- package/dist/ProfileSelector/index.d.ts +3 -2
- package/dist/ProfileSelector/index.js +8 -9
- package/dist/ProfileSelector/useAutoQuerySelector.d.ts +5 -1
- package/dist/ProfileSelector/useAutoQuerySelector.js +42 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +2 -2
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -3
- package/src/ProfileExplorer/index.tsx +1 -31
- package/src/ProfileSelector/index.tsx +6 -15
- package/src/ProfileSelector/useAutoQuerySelector.ts +58 -0
- package/src/index.tsx +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.16.392](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.391...@parca/profile@0.16.392) (2024-06-27)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## 0.16.391 (2024-06-24)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.390](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.389...@parca/profile@0.16.390) (2024-06-20)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -10,6 +10,6 @@ const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profile
|
|
|
10
10
|
const closeProfileB = () => {
|
|
11
11
|
closeProfile('B');
|
|
12
12
|
};
|
|
13
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between gap-2", children: [_jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true,
|
|
13
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between gap-2", children: [_jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo }) }), _jsx(Card, { className: "mt-2 p-2", 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 }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { children: _jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { navigateTo: navigateTo, queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource()) }) }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
|
|
14
14
|
};
|
|
15
15
|
export default ProfileExplorerCompare;
|
|
@@ -9,8 +9,7 @@ interface ProfileExplorerSingleProps {
|
|
|
9
9
|
selectQuery: (query: QuerySelection) => void;
|
|
10
10
|
selectProfile: (source: ProfileSelection) => void;
|
|
11
11
|
profile: ProfileSelection | null;
|
|
12
|
-
compareProfile: () => void;
|
|
13
12
|
navigateTo: NavigateFunction;
|
|
14
13
|
}
|
|
15
|
-
declare const ProfileExplorerSingle: ({ queryClient, query, selectQuery, selectProfile, profile,
|
|
14
|
+
declare const ProfileExplorerSingle: ({ queryClient, query, selectQuery, selectProfile, profile, navigateTo, }: ProfileExplorerSingleProps) => JSX.Element;
|
|
16
15
|
export default ProfileExplorerSingle;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Card } from '@parca/components';
|
|
3
3
|
import { ProfileViewWithData } from '..';
|
|
4
4
|
import ProfileSelector from '../ProfileSelector';
|
|
5
|
-
const ProfileExplorerSingle = ({ queryClient, query, selectQuery, selectProfile, profile,
|
|
6
|
-
return (_jsxs(_Fragment, { children: [_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: query, selectQuery: selectQuery, selectProfile: selectProfile, closeProfile: () => { }, profileSelection: profile, comparing: false,
|
|
5
|
+
const ProfileExplorerSingle = ({ queryClient, query, selectQuery, selectProfile, profile, navigateTo, }) => {
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: query, selectQuery: selectQuery, selectProfile: selectProfile, closeProfile: () => { }, profileSelection: profile, comparing: false, enforcedProfileName: '', navigateTo: navigateTo }) }), profile != null ? (_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: profile.ProfileSource(), navigateTo: navigateTo }) })) : (_jsx(_Fragment, {}))] }));
|
|
7
7
|
};
|
|
8
8
|
export default ProfileExplorerSingle;
|
|
@@ -6,5 +6,6 @@ interface ProfileExplorerProps {
|
|
|
6
6
|
queryParams: any;
|
|
7
7
|
navigateTo: NavigateFunction;
|
|
8
8
|
}
|
|
9
|
+
export declare const getExpressionAsAString: (expression: string | []) => string;
|
|
9
10
|
declare const ProfileExplorer: ({ queryClient, queryParams, navigateTo, }: ProfileExplorerProps) => JSX.Element;
|
|
10
11
|
export default ProfileExplorer;
|
|
@@ -23,7 +23,7 @@ import ProfileExplorerSingle from './ProfileExplorerSingle';
|
|
|
23
23
|
const ErrorContent = ({ errorMessage }) => {
|
|
24
24
|
return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
|
|
25
25
|
};
|
|
26
|
-
const getExpressionAsAString = (expression) => {
|
|
26
|
+
export const getExpressionAsAString = (expression) => {
|
|
27
27
|
const x = Array.isArray(expression) ? expression.join() : expression;
|
|
28
28
|
return x;
|
|
29
29
|
};
|
|
@@ -168,32 +168,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
|
|
|
168
168
|
dashboard_items: dashboard_items ?? DEFAULT_DASHBOARD_ITEMS,
|
|
169
169
|
});
|
|
170
170
|
};
|
|
171
|
-
|
|
172
|
-
let compareQuery = {
|
|
173
|
-
compare_a: 'true',
|
|
174
|
-
expression_a: encodeURIComponent(queryA.expression),
|
|
175
|
-
from_a: queryA.from.toString(),
|
|
176
|
-
to_a: queryA.to.toString(),
|
|
177
|
-
time_selection_a: queryA.timeSelection,
|
|
178
|
-
compare_b: 'true',
|
|
179
|
-
expression_b: encodeURIComponent(queryA.expression),
|
|
180
|
-
from_b: queryA.from.toString(),
|
|
181
|
-
to_b: queryA.to.toString(),
|
|
182
|
-
time_selection_b: queryA.timeSelection,
|
|
183
|
-
};
|
|
184
|
-
if (profileA != null) {
|
|
185
|
-
compareQuery = {
|
|
186
|
-
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
187
|
-
...compareQuery,
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
void navigateTo('/', {
|
|
191
|
-
...compareQuery,
|
|
192
|
-
search_string: '',
|
|
193
|
-
dashboard_items: dashboard_items ?? DEFAULT_DASHBOARD_ITEMS,
|
|
194
|
-
});
|
|
195
|
-
};
|
|
196
|
-
return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: queryA, profile: profileA, selectQuery: selectQuery, selectProfile: selectProfile, compareProfile: compareProfile, navigateTo: navigateTo }));
|
|
171
|
+
return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: queryA, profile: profileA, selectQuery: selectQuery, selectProfile: selectProfile, navigateTo: navigateTo }));
|
|
197
172
|
}
|
|
198
173
|
const queryB = {
|
|
199
174
|
expression: expression_b,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { RpcError } from '@protobuf-ts/runtime-rpc';
|
|
3
3
|
import { ProfileTypesResponse, QueryServiceClient } from '@parca/client';
|
|
4
|
+
import { type NavigateFunction } from '@parca/utilities';
|
|
4
5
|
import { ProfileSelection } from '..';
|
|
5
6
|
export interface QuerySelection {
|
|
6
7
|
expression: string;
|
|
@@ -19,7 +20,7 @@ interface ProfileSelectorProps {
|
|
|
19
20
|
enforcedProfileName: string;
|
|
20
21
|
profileSelection: ProfileSelection | null;
|
|
21
22
|
comparing: boolean;
|
|
22
|
-
|
|
23
|
+
navigateTo: NavigateFunction;
|
|
23
24
|
}
|
|
24
25
|
export interface IProfileTypesResult {
|
|
25
26
|
loading: boolean;
|
|
@@ -27,5 +28,5 @@ export interface IProfileTypesResult {
|
|
|
27
28
|
error?: RpcError;
|
|
28
29
|
}
|
|
29
30
|
export declare const useProfileTypes: (client: QueryServiceClient) => IProfileTypesResult;
|
|
30
|
-
declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing,
|
|
31
|
+
declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, }: ProfileSelectorProps) => JSX.Element;
|
|
31
32
|
export default ProfileSelector;
|
|
@@ -20,7 +20,6 @@ import MatchersInput from '../MatchersInput/index';
|
|
|
20
20
|
import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
|
|
21
21
|
import ProfileMetricsGraph, { ProfileMetricsEmptyState } from '../ProfileMetricsGraph';
|
|
22
22
|
import ProfileTypeSelector from '../ProfileTypeSelector/index';
|
|
23
|
-
import CompareButton from './CompareButton';
|
|
24
23
|
import { useAutoQuerySelector } from './useAutoQuerySelector';
|
|
25
24
|
export const useProfileTypes = (client) => {
|
|
26
25
|
const [result, setResult] = useState(undefined);
|
|
@@ -39,7 +38,7 @@ export const useProfileTypes = (client) => {
|
|
|
39
38
|
}, [client, metadata, loading]);
|
|
40
39
|
return { loading, data: result, error };
|
|
41
40
|
};
|
|
42
|
-
const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing,
|
|
41
|
+
const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, }) => {
|
|
43
42
|
const { loading: profileTypesLoading, data: profileTypesData, error, } = useProfileTypes(queryClient);
|
|
44
43
|
const { heightStyle } = useMetricsGraphDimensions(comparing);
|
|
45
44
|
const { viewComponent } = useParcaContext();
|
|
@@ -137,17 +136,17 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
|
|
|
137
136
|
profileTypesData,
|
|
138
137
|
setProfileName,
|
|
139
138
|
setQueryExpression,
|
|
139
|
+
querySelection,
|
|
140
|
+
navigateTo,
|
|
140
141
|
});
|
|
141
|
-
const handleCompareClick = () => onCompareProfile();
|
|
142
142
|
const searchDisabled = queryExpressionString === undefined ||
|
|
143
143
|
queryExpressionString === '' ||
|
|
144
144
|
queryExpressionString === '{}';
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}, id: "h-matcher-search-button", children: "Search" })] })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
|
|
145
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex gap-2", children: [_jsxs("div", { className: "flex w-full flex-wrap content-start items-center gap-2", children: [_jsxs("div", { className: "pb-6", children: [_jsx("label", { className: "text-xs", children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error, disabled: viewComponent?.disableProfileTypesDropdown })] }), _jsxs("div", { className: "w-full flex-1 pb-6", children: [_jsxs("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: [_jsx("label", { className: "text-xs", children: "Query" }), (query.matchers.length > 0 || query.inputMatcherString.length > 0) &&
|
|
146
|
+
viewComponent !== undefined && _jsx("div", { children: viewComponent?.createViewComponent })] }), _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
setQueryExpression(true);
|
|
149
|
+
}, id: "h-matcher-search-button", children: "Search" }) })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
|
|
151
150
|
querySelection.expression.length > 0 &&
|
|
152
151
|
querySelection.from !== undefined &&
|
|
153
152
|
querySelection.to !== undefined ? (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, setTimeRange: (range) => {
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { ProfileTypesResponse } from '@parca/client';
|
|
2
|
+
import { type NavigateFunction } from '@parca/utilities';
|
|
3
|
+
import { QuerySelection } from '../ProfileSelector';
|
|
2
4
|
interface Props {
|
|
3
5
|
selectedProfileName: string;
|
|
4
6
|
profileTypesData: ProfileTypesResponse | undefined;
|
|
5
7
|
setProfileName: (name: string) => void;
|
|
6
8
|
setQueryExpression: () => void;
|
|
9
|
+
querySelection: QuerySelection;
|
|
10
|
+
navigateTo: NavigateFunction;
|
|
7
11
|
}
|
|
8
|
-
export declare const useAutoQuerySelector: ({ selectedProfileName, profileTypesData, setProfileName, setQueryExpression, }: Props) => void;
|
|
12
|
+
export declare const useAutoQuerySelector: ({ selectedProfileName, profileTypesData, setProfileName, setQueryExpression, querySelection, navigateTo, }: Props) => void;
|
|
9
13
|
export {};
|
|
@@ -12,10 +12,51 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { useEffect } from 'react';
|
|
14
14
|
import { selectAutoQuery, setAutoQuery, useAppDispatch, useAppSelector } from '@parca/store';
|
|
15
|
+
import { ProfileSelectionFromParams, SuffixParams } from '..';
|
|
15
16
|
import { constructProfileName } from '../ProfileTypeSelector';
|
|
16
|
-
export const useAutoQuerySelector = ({ selectedProfileName, profileTypesData, setProfileName, setQueryExpression, }) => {
|
|
17
|
+
export const useAutoQuerySelector = ({ selectedProfileName, profileTypesData, setProfileName, setQueryExpression, querySelection, navigateTo, }) => {
|
|
17
18
|
const autoQuery = useAppSelector(selectAutoQuery);
|
|
18
19
|
const dispatch = useAppDispatch();
|
|
20
|
+
const queryParams = new URLSearchParams(location.search);
|
|
21
|
+
const comparing = queryParams.get('comparing') === 'true';
|
|
22
|
+
const expressionA = queryParams.get('expression_a');
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (comparing && expressionA !== null && expressionA !== undefined) {
|
|
25
|
+
if (querySelection.expression === undefined) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const profileA = ProfileSelectionFromParams(querySelection.mergeFrom?.toString(), querySelection.mergeTo?.toString(), querySelection.expression, '');
|
|
29
|
+
const queryA = {
|
|
30
|
+
expression: querySelection.expression,
|
|
31
|
+
from: querySelection.from,
|
|
32
|
+
to: querySelection.to,
|
|
33
|
+
timeSelection: querySelection.timeSelection,
|
|
34
|
+
};
|
|
35
|
+
let compareQuery = {
|
|
36
|
+
compare_a: 'true',
|
|
37
|
+
expression_a: encodeURIComponent(queryA.expression),
|
|
38
|
+
from_a: queryA.from.toString(),
|
|
39
|
+
to_a: queryA.to.toString(),
|
|
40
|
+
time_selection_a: queryA.timeSelection,
|
|
41
|
+
compare_b: 'true',
|
|
42
|
+
expression_b: encodeURIComponent(queryA.expression),
|
|
43
|
+
from_b: queryA.from.toString(),
|
|
44
|
+
to_b: queryA.to.toString(),
|
|
45
|
+
time_selection_b: queryA.timeSelection,
|
|
46
|
+
};
|
|
47
|
+
if (profileA != null) {
|
|
48
|
+
compareQuery = {
|
|
49
|
+
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
50
|
+
...compareQuery,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
void navigateTo('/', {
|
|
54
|
+
...compareQuery,
|
|
55
|
+
search_string: '',
|
|
56
|
+
dashboard_items: ['icicle'],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}, [comparing, querySelection, navigateTo, expressionA, dispatch]);
|
|
19
60
|
// Effect to load some initial data on load when is no selection
|
|
20
61
|
useEffect(() => {
|
|
21
62
|
void (async () => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Props as CallgraphProps } from './Callgraph';
|
|
2
|
-
import ProfileExplorer from './ProfileExplorer';
|
|
2
|
+
import ProfileExplorer, { getExpressionAsAString } from './ProfileExplorer';
|
|
3
3
|
import ProfileTypeSelector from './ProfileTypeSelector';
|
|
4
4
|
export * from './ProfileIcicleGraph/IcicleGraph';
|
|
5
5
|
export * from './ProfileIcicleGraph';
|
|
@@ -11,4 +11,4 @@ export * from './ProfileTypeSelector';
|
|
|
11
11
|
export * from './SourceView';
|
|
12
12
|
export { default as Callgraph } from './Callgraph';
|
|
13
13
|
export type { CallgraphProps };
|
|
14
|
-
export { ProfileExplorer, ProfileTypeSelector };
|
|
14
|
+
export { ProfileExplorer, ProfileTypeSelector, getExpressionAsAString };
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
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 ProfileExplorer from './ProfileExplorer';
|
|
13
|
+
import ProfileExplorer, { getExpressionAsAString } from './ProfileExplorer';
|
|
14
14
|
import ProfileTypeSelector from './ProfileTypeSelector';
|
|
15
15
|
export * from './ProfileIcicleGraph/IcicleGraph';
|
|
16
16
|
export * from './ProfileIcicleGraph';
|
|
@@ -21,4 +21,4 @@ export * from './utils';
|
|
|
21
21
|
export * from './ProfileTypeSelector';
|
|
22
22
|
export * from './SourceView';
|
|
23
23
|
export { default as Callgraph } from './Callgraph';
|
|
24
|
-
export { ProfileExplorer, ProfileTypeSelector };
|
|
24
|
+
export { ProfileExplorer, ProfileTypeSelector, getExpressionAsAString };
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.392",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@headlessui/react": "^1.7.19",
|
|
7
7
|
"@iconify/react": "^4.0.0",
|
|
8
8
|
"@parca/client": "0.16.117",
|
|
9
|
-
"@parca/components": "0.16.
|
|
9
|
+
"@parca/components": "0.16.284",
|
|
10
10
|
"@parca/dynamicsize": "0.16.65",
|
|
11
11
|
"@parca/hooks": "0.0.60",
|
|
12
12
|
"@parca/icons": "0.16.69",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"access": "public",
|
|
72
72
|
"registry": "https://registry.npmjs.org/"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "5355cd41303f7388e15c70b63c26b22d0cf82830"
|
|
75
75
|
}
|
|
@@ -69,7 +69,7 @@ const ProfileExplorerCompare = ({
|
|
|
69
69
|
closeProfile={closeProfileA}
|
|
70
70
|
enforcedProfileName={''}
|
|
71
71
|
comparing={true}
|
|
72
|
-
|
|
72
|
+
navigateTo={navigateTo}
|
|
73
73
|
/>
|
|
74
74
|
</Card>
|
|
75
75
|
<Card className="mt-2 p-2">
|
|
@@ -82,7 +82,7 @@ const ProfileExplorerCompare = ({
|
|
|
82
82
|
closeProfile={closeProfileB}
|
|
83
83
|
enforcedProfileName={Query.parse(queryA.expression).profileName()}
|
|
84
84
|
comparing={true}
|
|
85
|
-
|
|
85
|
+
navigateTo={navigateTo}
|
|
86
86
|
/>
|
|
87
87
|
</Card>
|
|
88
88
|
</div>
|
|
@@ -24,7 +24,6 @@ interface ProfileExplorerSingleProps {
|
|
|
24
24
|
selectQuery: (query: QuerySelection) => void;
|
|
25
25
|
selectProfile: (source: ProfileSelection) => void;
|
|
26
26
|
profile: ProfileSelection | null;
|
|
27
|
-
compareProfile: () => void;
|
|
28
27
|
navigateTo: NavigateFunction;
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -34,7 +33,6 @@ const ProfileExplorerSingle = ({
|
|
|
34
33
|
selectQuery,
|
|
35
34
|
selectProfile,
|
|
36
35
|
profile,
|
|
37
|
-
compareProfile,
|
|
38
36
|
navigateTo,
|
|
39
37
|
}: ProfileExplorerSingleProps): JSX.Element => {
|
|
40
38
|
return (
|
|
@@ -48,8 +46,8 @@ const ProfileExplorerSingle = ({
|
|
|
48
46
|
closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
|
|
49
47
|
profileSelection={profile}
|
|
50
48
|
comparing={false}
|
|
51
|
-
onCompareProfile={compareProfile}
|
|
52
49
|
enforcedProfileName={''} // TODO
|
|
50
|
+
navigateTo={navigateTo}
|
|
53
51
|
/>
|
|
54
52
|
</Card>
|
|
55
53
|
{profile != null ? (
|
|
@@ -42,7 +42,7 @@ const ErrorContent = ({errorMessage}: {errorMessage: string}): JSX.Element => {
|
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const getExpressionAsAString = (expression: string | []): string => {
|
|
45
|
+
export const getExpressionAsAString = (expression: string | []): string => {
|
|
46
46
|
const x = Array.isArray(expression) ? expression.join() : expression;
|
|
47
47
|
return x;
|
|
48
48
|
};
|
|
@@ -263,35 +263,6 @@ const ProfileExplorerApp = ({
|
|
|
263
263
|
});
|
|
264
264
|
};
|
|
265
265
|
|
|
266
|
-
const compareProfile = (): void => {
|
|
267
|
-
let compareQuery = {
|
|
268
|
-
compare_a: 'true',
|
|
269
|
-
expression_a: encodeURIComponent(queryA.expression),
|
|
270
|
-
from_a: queryA.from.toString(),
|
|
271
|
-
to_a: queryA.to.toString(),
|
|
272
|
-
time_selection_a: queryA.timeSelection,
|
|
273
|
-
|
|
274
|
-
compare_b: 'true',
|
|
275
|
-
expression_b: encodeURIComponent(queryA.expression),
|
|
276
|
-
from_b: queryA.from.toString(),
|
|
277
|
-
to_b: queryA.to.toString(),
|
|
278
|
-
time_selection_b: queryA.timeSelection,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
if (profileA != null) {
|
|
282
|
-
compareQuery = {
|
|
283
|
-
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
284
|
-
...compareQuery,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
void navigateTo('/', {
|
|
289
|
-
...compareQuery,
|
|
290
|
-
search_string: '',
|
|
291
|
-
dashboard_items: dashboard_items ?? DEFAULT_DASHBOARD_ITEMS,
|
|
292
|
-
});
|
|
293
|
-
};
|
|
294
|
-
|
|
295
266
|
return (
|
|
296
267
|
<ProfileExplorerSingle
|
|
297
268
|
queryClient={queryClient}
|
|
@@ -299,7 +270,6 @@ const ProfileExplorerApp = ({
|
|
|
299
270
|
profile={profileA}
|
|
300
271
|
selectQuery={selectQuery}
|
|
301
272
|
selectProfile={selectProfile}
|
|
302
|
-
compareProfile={compareProfile}
|
|
303
273
|
navigateTo={navigateTo}
|
|
304
274
|
/>
|
|
305
275
|
);
|
|
@@ -27,13 +27,13 @@ import {
|
|
|
27
27
|
} from '@parca/components';
|
|
28
28
|
import {CloseIcon} from '@parca/icons';
|
|
29
29
|
import {Query} from '@parca/parser';
|
|
30
|
+
import {type NavigateFunction} from '@parca/utilities';
|
|
30
31
|
|
|
31
32
|
import {MergedProfileSelection, ProfileSelection} from '..';
|
|
32
33
|
import MatchersInput from '../MatchersInput/index';
|
|
33
34
|
import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
|
|
34
35
|
import ProfileMetricsGraph, {ProfileMetricsEmptyState} from '../ProfileMetricsGraph';
|
|
35
36
|
import ProfileTypeSelector from '../ProfileTypeSelector/index';
|
|
36
|
-
import CompareButton from './CompareButton';
|
|
37
37
|
import {useAutoQuerySelector} from './useAutoQuerySelector';
|
|
38
38
|
|
|
39
39
|
export interface QuerySelection {
|
|
@@ -54,7 +54,7 @@ interface ProfileSelectorProps {
|
|
|
54
54
|
enforcedProfileName: string;
|
|
55
55
|
profileSelection: ProfileSelection | null;
|
|
56
56
|
comparing: boolean;
|
|
57
|
-
|
|
57
|
+
navigateTo: NavigateFunction;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export interface IProfileTypesResult {
|
|
@@ -92,7 +92,7 @@ const ProfileSelector = ({
|
|
|
92
92
|
enforcedProfileName,
|
|
93
93
|
profileSelection,
|
|
94
94
|
comparing,
|
|
95
|
-
|
|
95
|
+
navigateTo,
|
|
96
96
|
}: ProfileSelectorProps): JSX.Element => {
|
|
97
97
|
const {
|
|
98
98
|
loading: profileTypesLoading,
|
|
@@ -217,21 +217,19 @@ const ProfileSelector = ({
|
|
|
217
217
|
profileTypesData,
|
|
218
218
|
setProfileName,
|
|
219
219
|
setQueryExpression,
|
|
220
|
+
querySelection,
|
|
221
|
+
navigateTo,
|
|
220
222
|
});
|
|
221
223
|
|
|
222
|
-
const handleCompareClick = (): void => onCompareProfile();
|
|
223
|
-
|
|
224
224
|
const searchDisabled =
|
|
225
225
|
queryExpressionString === undefined ||
|
|
226
226
|
queryExpressionString === '' ||
|
|
227
227
|
queryExpressionString === '{}';
|
|
228
228
|
|
|
229
|
-
const compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
|
|
230
|
-
|
|
231
229
|
return (
|
|
232
230
|
<>
|
|
233
231
|
<div className="mb-2 flex gap-2">
|
|
234
|
-
<div className="flex w-full flex-wrap content-start items-center
|
|
232
|
+
<div className="flex w-full flex-wrap content-start items-center gap-2">
|
|
235
233
|
<div className="pb-6">
|
|
236
234
|
<label className="text-xs">Profile type</label>
|
|
237
235
|
<ProfileTypeSelector
|
|
@@ -261,13 +259,6 @@ const ProfileSelector = ({
|
|
|
261
259
|
range={timeRangeSelection}
|
|
262
260
|
/>
|
|
263
261
|
<ButtonGroup>
|
|
264
|
-
{!searchDisabled && (
|
|
265
|
-
<>
|
|
266
|
-
{!comparing && (
|
|
267
|
-
<CompareButton disabled={compareDisabled} onClick={handleCompareClick} />
|
|
268
|
-
)}
|
|
269
|
-
</>
|
|
270
|
-
)}
|
|
271
262
|
<Button
|
|
272
263
|
disabled={searchDisabled}
|
|
273
264
|
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
|
@@ -15,7 +15,10 @@ import {useEffect} from 'react';
|
|
|
15
15
|
|
|
16
16
|
import {ProfileTypesResponse} from '@parca/client';
|
|
17
17
|
import {selectAutoQuery, setAutoQuery, useAppDispatch, useAppSelector} from '@parca/store';
|
|
18
|
+
import {type NavigateFunction} from '@parca/utilities';
|
|
18
19
|
|
|
20
|
+
import {ProfileSelectionFromParams, SuffixParams} from '..';
|
|
21
|
+
import {QuerySelection} from '../ProfileSelector';
|
|
19
22
|
import {constructProfileName} from '../ProfileTypeSelector';
|
|
20
23
|
|
|
21
24
|
interface Props {
|
|
@@ -23,6 +26,8 @@ interface Props {
|
|
|
23
26
|
profileTypesData: ProfileTypesResponse | undefined;
|
|
24
27
|
setProfileName: (name: string) => void;
|
|
25
28
|
setQueryExpression: () => void;
|
|
29
|
+
querySelection: QuerySelection;
|
|
30
|
+
navigateTo: NavigateFunction;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
export const useAutoQuerySelector = ({
|
|
@@ -30,9 +35,62 @@ export const useAutoQuerySelector = ({
|
|
|
30
35
|
profileTypesData,
|
|
31
36
|
setProfileName,
|
|
32
37
|
setQueryExpression,
|
|
38
|
+
querySelection,
|
|
39
|
+
navigateTo,
|
|
33
40
|
}: Props): void => {
|
|
34
41
|
const autoQuery = useAppSelector(selectAutoQuery);
|
|
35
42
|
const dispatch = useAppDispatch();
|
|
43
|
+
const queryParams = new URLSearchParams(location.search);
|
|
44
|
+
|
|
45
|
+
const comparing = queryParams.get('comparing') === 'true';
|
|
46
|
+
const expressionA = queryParams.get('expression_a');
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (comparing && expressionA !== null && expressionA !== undefined) {
|
|
50
|
+
if (querySelection.expression === undefined) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const profileA = ProfileSelectionFromParams(
|
|
54
|
+
querySelection.mergeFrom?.toString(),
|
|
55
|
+
querySelection.mergeTo?.toString(),
|
|
56
|
+
querySelection.expression,
|
|
57
|
+
''
|
|
58
|
+
);
|
|
59
|
+
const queryA = {
|
|
60
|
+
expression: querySelection.expression,
|
|
61
|
+
from: querySelection.from,
|
|
62
|
+
to: querySelection.to,
|
|
63
|
+
timeSelection: querySelection.timeSelection,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
let compareQuery = {
|
|
67
|
+
compare_a: 'true',
|
|
68
|
+
expression_a: encodeURIComponent(queryA.expression),
|
|
69
|
+
from_a: queryA.from.toString(),
|
|
70
|
+
to_a: queryA.to.toString(),
|
|
71
|
+
time_selection_a: queryA.timeSelection,
|
|
72
|
+
|
|
73
|
+
compare_b: 'true',
|
|
74
|
+
expression_b: encodeURIComponent(queryA.expression),
|
|
75
|
+
from_b: queryA.from.toString(),
|
|
76
|
+
to_b: queryA.to.toString(),
|
|
77
|
+
time_selection_b: queryA.timeSelection,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
if (profileA != null) {
|
|
81
|
+
compareQuery = {
|
|
82
|
+
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
83
|
+
...compareQuery,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void navigateTo('/', {
|
|
88
|
+
...compareQuery,
|
|
89
|
+
search_string: '',
|
|
90
|
+
dashboard_items: ['icicle'],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}, [comparing, querySelection, navigateTo, expressionA, dispatch]);
|
|
36
94
|
|
|
37
95
|
// Effect to load some initial data on load when is no selection
|
|
38
96
|
useEffect(() => {
|
package/src/index.tsx
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
14
|
import type {Props as CallgraphProps} from './Callgraph';
|
|
15
|
-
import ProfileExplorer from './ProfileExplorer';
|
|
15
|
+
import ProfileExplorer, {getExpressionAsAString} from './ProfileExplorer';
|
|
16
16
|
import ProfileTypeSelector from './ProfileTypeSelector';
|
|
17
17
|
|
|
18
18
|
export * from './ProfileIcicleGraph/IcicleGraph';
|
|
@@ -27,4 +27,4 @@ export {default as Callgraph} from './Callgraph';
|
|
|
27
27
|
|
|
28
28
|
export type {CallgraphProps};
|
|
29
29
|
|
|
30
|
-
export {ProfileExplorer, ProfileTypeSelector};
|
|
30
|
+
export {ProfileExplorer, ProfileTypeSelector, getExpressionAsAString};
|