@parca/profile 0.16.389 → 0.16.391
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 +1 -2
- package/dist/ProfileSelector/index.js +6 -9
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +46 -0
- package/package.json +3 -3
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +0 -2
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +0 -3
- package/src/ProfileExplorer/index.tsx +1 -31
- package/src/ProfileSelector/index.tsx +1 -15
- package/src/index.tsx +2 -2
- package/src/utils.ts +73 -0
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.391 (2024-06-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.16.390](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.389...@parca/profile@0.16.390) (2024-06-20)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## 0.16.389 (2024-06-18)
|
|
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 }) }), _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 }) })] }), _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: '' }) }), 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,
|
|
@@ -19,7 +19,6 @@ interface ProfileSelectorProps {
|
|
|
19
19
|
enforcedProfileName: string;
|
|
20
20
|
profileSelection: ProfileSelection | null;
|
|
21
21
|
comparing: boolean;
|
|
22
|
-
onCompareProfile: () => void;
|
|
23
22
|
}
|
|
24
23
|
export interface IProfileTypesResult {
|
|
25
24
|
loading: boolean;
|
|
@@ -27,5 +26,5 @@ export interface IProfileTypesResult {
|
|
|
27
26
|
error?: RpcError;
|
|
28
27
|
}
|
|
29
28
|
export declare const useProfileTypes: (client: QueryServiceClient) => IProfileTypesResult;
|
|
30
|
-
declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing,
|
|
29
|
+
declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, }: ProfileSelectorProps) => JSX.Element;
|
|
31
30
|
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, }) => {
|
|
43
42
|
const { loading: profileTypesLoading, data: profileTypesData, error, } = useProfileTypes(queryClient);
|
|
44
43
|
const { heightStyle } = useMetricsGraphDimensions(comparing);
|
|
45
44
|
const { viewComponent } = useParcaContext();
|
|
@@ -138,16 +137,14 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
|
|
|
138
137
|
setProfileName,
|
|
139
138
|
setQueryExpression,
|
|
140
139
|
});
|
|
141
|
-
const handleCompareClick = () => onCompareProfile();
|
|
142
140
|
const searchDisabled = queryExpressionString === undefined ||
|
|
143
141
|
queryExpressionString === '' ||
|
|
144
142
|
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 &&
|
|
143
|
+
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) &&
|
|
144
|
+
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) => {
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
setQueryExpression(true);
|
|
147
|
+
}, 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
148
|
querySelection.expression.length > 0 &&
|
|
152
149
|
querySelection.from !== undefined &&
|
|
153
150
|
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) => {
|
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/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { RpcMetadata } from '@protobuf-ts/runtime-rpc';
|
|
2
2
|
import { QueryRequest, QueryServiceClient } from '@parca/client';
|
|
3
|
+
import { type NavigateFunction } from '@parca/utilities';
|
|
3
4
|
export declare const hexifyAddress: (address?: bigint) => string;
|
|
4
5
|
export declare const downloadPprof: (request: QueryRequest, queryClient: QueryServiceClient, metadata: RpcMetadata) => Promise<Blob>;
|
|
5
6
|
export declare const truncateString: (str: string, num: number) => string;
|
|
6
7
|
export declare const truncateStringReverse: (str: string, num: number) => string;
|
|
8
|
+
export declare const compareProfile: (navigateTo: NavigateFunction, defaultDashboardItems?: string[]) => void;
|
package/dist/utils.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { QueryRequest_ReportType } from '@parca/client';
|
|
14
|
+
import { parseParams } from '@parca/utilities';
|
|
15
|
+
import { ProfileSelectionFromParams, SuffixParams, getExpressionAsAString } from '.';
|
|
14
16
|
export const hexifyAddress = (address) => {
|
|
15
17
|
if (address == null) {
|
|
16
18
|
return '';
|
|
@@ -41,3 +43,47 @@ export const truncateStringReverse = (str, num) => {
|
|
|
41
43
|
}
|
|
42
44
|
return '...' + str.slice(str.length - num);
|
|
43
45
|
};
|
|
46
|
+
export const compareProfile = (navigateTo, defaultDashboardItems = ['icicle']) => {
|
|
47
|
+
const queryParams = parseParams(window.location.search);
|
|
48
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
49
|
+
const { from_a, to_a, merge_from_a, merge_to_a, time_selection_a, filter_by_function, dashboard_items, } = queryParams;
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
51
|
+
const selection_a = getExpressionAsAString(queryParams.selection_a);
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
53
|
+
const expression_a = getExpressionAsAString(queryParams.expression_a);
|
|
54
|
+
if (expression_a === undefined || selection_a === undefined) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const mergeFrom = merge_from_a ?? undefined;
|
|
58
|
+
const mergeTo = merge_to_a ?? undefined;
|
|
59
|
+
const profileA = ProfileSelectionFromParams(mergeFrom, mergeTo, selection_a, filter_by_function);
|
|
60
|
+
const queryA = {
|
|
61
|
+
expression: expression_a,
|
|
62
|
+
from: parseInt(from_a),
|
|
63
|
+
to: parseInt(to_a),
|
|
64
|
+
timeSelection: time_selection_a,
|
|
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
|
+
compare_b: 'true',
|
|
73
|
+
expression_b: encodeURIComponent(queryA.expression),
|
|
74
|
+
from_b: queryA.from.toString(),
|
|
75
|
+
to_b: queryA.to.toString(),
|
|
76
|
+
time_selection_b: queryA.timeSelection,
|
|
77
|
+
};
|
|
78
|
+
if (profileA != null) {
|
|
79
|
+
compareQuery = {
|
|
80
|
+
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
81
|
+
...compareQuery,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
void navigateTo('/', {
|
|
85
|
+
...compareQuery,
|
|
86
|
+
search_string: '',
|
|
87
|
+
dashboard_items: dashboard_items ?? defaultDashboardItems,
|
|
88
|
+
});
|
|
89
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.391",
|
|
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": "db964de537aebc04da1d2741dcf14f691d78a6a0"
|
|
75
75
|
}
|
|
@@ -69,7 +69,6 @@ const ProfileExplorerCompare = ({
|
|
|
69
69
|
closeProfile={closeProfileA}
|
|
70
70
|
enforcedProfileName={''}
|
|
71
71
|
comparing={true}
|
|
72
|
-
onCompareProfile={() => {}}
|
|
73
72
|
/>
|
|
74
73
|
</Card>
|
|
75
74
|
<Card className="mt-2 p-2">
|
|
@@ -82,7 +81,6 @@ const ProfileExplorerCompare = ({
|
|
|
82
81
|
closeProfile={closeProfileB}
|
|
83
82
|
enforcedProfileName={Query.parse(queryA.expression).profileName()}
|
|
84
83
|
comparing={true}
|
|
85
|
-
onCompareProfile={() => {}}
|
|
86
84
|
/>
|
|
87
85
|
</Card>
|
|
88
86
|
</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,7 +46,6 @@ 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
|
|
53
50
|
/>
|
|
54
51
|
</Card>
|
|
@@ -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
|
);
|
|
@@ -33,7 +33,6 @@ import MatchersInput from '../MatchersInput/index';
|
|
|
33
33
|
import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
|
|
34
34
|
import ProfileMetricsGraph, {ProfileMetricsEmptyState} from '../ProfileMetricsGraph';
|
|
35
35
|
import ProfileTypeSelector from '../ProfileTypeSelector/index';
|
|
36
|
-
import CompareButton from './CompareButton';
|
|
37
36
|
import {useAutoQuerySelector} from './useAutoQuerySelector';
|
|
38
37
|
|
|
39
38
|
export interface QuerySelection {
|
|
@@ -54,7 +53,6 @@ interface ProfileSelectorProps {
|
|
|
54
53
|
enforcedProfileName: string;
|
|
55
54
|
profileSelection: ProfileSelection | null;
|
|
56
55
|
comparing: boolean;
|
|
57
|
-
onCompareProfile: () => void;
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
export interface IProfileTypesResult {
|
|
@@ -92,7 +90,6 @@ const ProfileSelector = ({
|
|
|
92
90
|
enforcedProfileName,
|
|
93
91
|
profileSelection,
|
|
94
92
|
comparing,
|
|
95
|
-
onCompareProfile,
|
|
96
93
|
}: ProfileSelectorProps): JSX.Element => {
|
|
97
94
|
const {
|
|
98
95
|
loading: profileTypesLoading,
|
|
@@ -219,19 +216,15 @@ const ProfileSelector = ({
|
|
|
219
216
|
setQueryExpression,
|
|
220
217
|
});
|
|
221
218
|
|
|
222
|
-
const handleCompareClick = (): void => onCompareProfile();
|
|
223
|
-
|
|
224
219
|
const searchDisabled =
|
|
225
220
|
queryExpressionString === undefined ||
|
|
226
221
|
queryExpressionString === '' ||
|
|
227
222
|
queryExpressionString === '{}';
|
|
228
223
|
|
|
229
|
-
const compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
|
|
230
|
-
|
|
231
224
|
return (
|
|
232
225
|
<>
|
|
233
226
|
<div className="mb-2 flex gap-2">
|
|
234
|
-
<div className="flex w-full flex-wrap content-start items-center
|
|
227
|
+
<div className="flex w-full flex-wrap content-start items-center gap-2">
|
|
235
228
|
<div className="pb-6">
|
|
236
229
|
<label className="text-xs">Profile type</label>
|
|
237
230
|
<ProfileTypeSelector
|
|
@@ -261,13 +254,6 @@ const ProfileSelector = ({
|
|
|
261
254
|
range={timeRangeSelection}
|
|
262
255
|
/>
|
|
263
256
|
<ButtonGroup>
|
|
264
|
-
{!searchDisabled && (
|
|
265
|
-
<>
|
|
266
|
-
{!comparing && (
|
|
267
|
-
<CompareButton disabled={compareDisabled} onClick={handleCompareClick} />
|
|
268
|
-
)}
|
|
269
|
-
</>
|
|
270
|
-
)}
|
|
271
257
|
<Button
|
|
272
258
|
disabled={searchDisabled}
|
|
273
259
|
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
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};
|
package/src/utils.ts
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
import type {RpcMetadata} from '@protobuf-ts/runtime-rpc';
|
|
15
15
|
|
|
16
16
|
import {QueryRequest, QueryRequest_ReportType, QueryServiceClient} from '@parca/client';
|
|
17
|
+
import {parseParams, type NavigateFunction} from '@parca/utilities';
|
|
18
|
+
|
|
19
|
+
import {ProfileSelectionFromParams, SuffixParams, getExpressionAsAString} from '.';
|
|
17
20
|
|
|
18
21
|
export const hexifyAddress = (address?: bigint): string => {
|
|
19
22
|
if (address == null) {
|
|
@@ -59,3 +62,73 @@ export const truncateStringReverse = (str: string, num: number): string => {
|
|
|
59
62
|
|
|
60
63
|
return '...' + str.slice(str.length - num);
|
|
61
64
|
};
|
|
65
|
+
|
|
66
|
+
export const compareProfile = (
|
|
67
|
+
navigateTo: NavigateFunction,
|
|
68
|
+
defaultDashboardItems: string[] = ['icicle']
|
|
69
|
+
): void => {
|
|
70
|
+
const queryParams = parseParams(window.location.search);
|
|
71
|
+
|
|
72
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
73
|
+
const {
|
|
74
|
+
from_a,
|
|
75
|
+
to_a,
|
|
76
|
+
merge_from_a,
|
|
77
|
+
merge_to_a,
|
|
78
|
+
time_selection_a,
|
|
79
|
+
filter_by_function,
|
|
80
|
+
dashboard_items,
|
|
81
|
+
} = queryParams;
|
|
82
|
+
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
84
|
+
const selection_a = getExpressionAsAString(queryParams.selection_a as string | []);
|
|
85
|
+
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
87
|
+
const expression_a = getExpressionAsAString(queryParams.expression_a as string | []);
|
|
88
|
+
|
|
89
|
+
if (expression_a === undefined || selection_a === undefined) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const mergeFrom = merge_from_a ?? undefined;
|
|
94
|
+
const mergeTo = merge_to_a ?? undefined;
|
|
95
|
+
const profileA = ProfileSelectionFromParams(
|
|
96
|
+
mergeFrom as string,
|
|
97
|
+
mergeTo as string,
|
|
98
|
+
selection_a,
|
|
99
|
+
filter_by_function as string
|
|
100
|
+
);
|
|
101
|
+
const queryA = {
|
|
102
|
+
expression: expression_a,
|
|
103
|
+
from: parseInt(from_a as string),
|
|
104
|
+
to: parseInt(to_a as string),
|
|
105
|
+
timeSelection: time_selection_a as string,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
let compareQuery = {
|
|
109
|
+
compare_a: 'true',
|
|
110
|
+
expression_a: encodeURIComponent(queryA.expression),
|
|
111
|
+
from_a: queryA.from.toString(),
|
|
112
|
+
to_a: queryA.to.toString(),
|
|
113
|
+
time_selection_a: queryA.timeSelection,
|
|
114
|
+
|
|
115
|
+
compare_b: 'true',
|
|
116
|
+
expression_b: encodeURIComponent(queryA.expression),
|
|
117
|
+
from_b: queryA.from.toString(),
|
|
118
|
+
to_b: queryA.to.toString(),
|
|
119
|
+
time_selection_b: queryA.timeSelection,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
if (profileA != null) {
|
|
123
|
+
compareQuery = {
|
|
124
|
+
...SuffixParams(profileA.HistoryParams(), '_a'),
|
|
125
|
+
...compareQuery,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
void navigateTo('/', {
|
|
130
|
+
...compareQuery,
|
|
131
|
+
search_string: '',
|
|
132
|
+
dashboard_items: dashboard_items ?? defaultDashboardItems,
|
|
133
|
+
});
|
|
134
|
+
};
|