@parca/profile 0.19.72 → 0.19.74
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/MatchersInput/index.d.ts.map +1 -1
- package/dist/MatchersInput/index.js +4 -2
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +1 -12
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +52 -11
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +1 -7
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +4 -2
- package/dist/ProfileExplorer/index.d.ts +1 -4
- package/dist/ProfileExplorer/index.d.ts.map +1 -1
- package/dist/ProfileExplorer/index.js +11 -225
- package/dist/ProfileMetricsGraph/index.d.ts +1 -1
- package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
- package/dist/ProfileMetricsGraph/index.js +16 -20
- package/dist/ProfileSelector/MetricsGraphSection.d.ts +3 -3
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +10 -6
- package/dist/ProfileSelector/index.d.ts +2 -7
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +40 -46
- package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
- package/dist/ProfileSelector/useAutoQuerySelector.js +19 -4
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +1 -1
- package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -1
- package/dist/ProfileView/components/ViewSelector/index.js +10 -4
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +4 -2
- package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useVisualizationState.js +20 -13
- package/dist/Table/MoreDropdown.d.ts.map +1 -1
- package/dist/Table/MoreDropdown.js +7 -3
- package/dist/Table/TableContextMenu.d.ts.map +1 -1
- package/dist/Table/TableContextMenu.js +9 -5
- package/dist/hooks/useCompareModeMeta.d.ts +10 -0
- package/dist/hooks/useCompareModeMeta.d.ts.map +1 -0
- package/dist/hooks/useCompareModeMeta.js +113 -0
- package/dist/hooks/useQueryState.d.ts +32 -0
- package/dist/hooks/useQueryState.d.ts.map +1 -0
- package/dist/hooks/useQueryState.js +285 -0
- package/dist/hooks/useQueryState.test.d.ts +2 -0
- package/dist/hooks/useQueryState.test.d.ts.map +1 -0
- package/dist/hooks/useQueryState.test.js +910 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/useSumBy.d.ts +7 -0
- package/dist/useSumBy.d.ts.map +1 -1
- package/dist/useSumBy.js +31 -6
- package/package.json +7 -7
- package/src/MatchersInput/index.tsx +4 -2
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +64 -46
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +7 -19
- package/src/ProfileExplorer/index.tsx +11 -339
- package/src/ProfileMetricsGraph/index.tsx +16 -20
- package/src/ProfileSelector/MetricsGraphSection.tsx +14 -10
- package/src/ProfileSelector/index.tsx +65 -83
- package/src/ProfileSelector/useAutoQuerySelector.ts +23 -5
- package/src/ProfileTypeSelector/index.tsx +3 -1
- package/src/ProfileView/components/ViewSelector/index.tsx +9 -4
- package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +4 -2
- package/src/ProfileView/hooks/useVisualizationState.ts +25 -12
- package/src/Table/MoreDropdown.tsx +7 -3
- package/src/Table/TableContextMenu.tsx +9 -5
- package/src/hooks/useCompareModeMeta.ts +131 -0
- package/src/hooks/useQueryState.test.tsx +1202 -0
- package/src/hooks/useQueryState.ts +414 -0
- package/src/index.tsx +9 -11
- package/src/useSumBy.ts +62 -7
- package/src/ProfileExplorer/index.test.ts +0 -97
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { ParamPreferences } from '@parca/components';
|
|
1
2
|
import { useLabelNames } from './MatchersInput';
|
|
2
|
-
import ProfileExplorer
|
|
3
|
+
import ProfileExplorer from './ProfileExplorer';
|
|
3
4
|
import ProfileTypeSelector from './ProfileTypeSelector';
|
|
4
5
|
import SelectWithRefresh from './SelectWithRefresh';
|
|
5
6
|
import CustomSelect from './SimpleMatchers/Select';
|
|
@@ -15,8 +16,6 @@ export * from './ProfileMetricsGraph';
|
|
|
15
16
|
export * from './useSumBy';
|
|
16
17
|
export { default as ProfileFilters } from './ProfileView/components/ProfileFilters';
|
|
17
18
|
export { useProfileFiltersUrlState } from './ProfileView/components/ProfileFilters/useProfileFiltersUrlState';
|
|
18
|
-
export declare const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES:
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
export { ProfileExplorer, ProfileTypeSelector, getExpressionAsAString, CustomSelect, SelectWithRefresh, useLabelNames, };
|
|
19
|
+
export declare const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES: ParamPreferences;
|
|
20
|
+
export { ProfileExplorer, ProfileTypeSelector, CustomSelect, SelectWithRefresh, useLabelNames };
|
|
22
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,2DAA2D,CAAC;AACnE,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAC,yBAAyB,EAAC,MAAM,mEAAmE,CAAC;AAE5G,eAAO,MAAM,qCAAqC,EAAE,gBAKnD,CAAC;AAEF,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { useLabelNames } from './MatchersInput';
|
|
14
|
-
import ProfileExplorer
|
|
14
|
+
import ProfileExplorer from './ProfileExplorer';
|
|
15
15
|
import ProfileTypeSelector from './ProfileTypeSelector';
|
|
16
16
|
import SelectWithRefresh from './SelectWithRefresh';
|
|
17
17
|
import CustomSelect from './SimpleMatchers/Select';
|
|
@@ -28,6 +28,9 @@ export * from './useSumBy';
|
|
|
28
28
|
export { default as ProfileFilters } from './ProfileView/components/ProfileFilters';
|
|
29
29
|
export { useProfileFiltersUrlState } from './ProfileView/components/ProfileFilters/useProfileFiltersUrlState';
|
|
30
30
|
export const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES = {
|
|
31
|
-
dashboard_items:
|
|
31
|
+
dashboard_items: {
|
|
32
|
+
defaultValue: 'flamegraph',
|
|
33
|
+
splitOnCommas: true, // This param should split on commas for array values
|
|
34
|
+
},
|
|
32
35
|
};
|
|
33
|
-
export { ProfileExplorer, ProfileTypeSelector,
|
|
36
|
+
export { ProfileExplorer, ProfileTypeSelector, CustomSelect, SelectWithRefresh, useLabelNames };
|
package/dist/useSumBy.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { QueryServiceClient } from '@parca/client';
|
|
2
|
+
import { DateTimeRange } from '@parca/components';
|
|
1
3
|
import { ProfileType } from '@parca/parser';
|
|
2
4
|
export declare const DEFAULT_EMPTY_SUM_BY: string[];
|
|
3
5
|
export declare const useSumBySelection: (profileType: ProfileType | undefined, labelNamesLoading: boolean, labels: string[] | undefined, { defaultValue, }?: {
|
|
@@ -11,4 +13,9 @@ export declare const useDefaultSumBy: (profileType: ProfileType | undefined, lab
|
|
|
11
13
|
};
|
|
12
14
|
export declare const useSumByFromParams: (param: string | string[] | undefined) => string[] | undefined;
|
|
13
15
|
export declare const sumByToParam: (sumBy: string[] | undefined) => string | string[] | undefined;
|
|
16
|
+
export declare const useSumBy: (queryClient: QueryServiceClient, profileType: ProfileType | undefined, timeRange: DateTimeRange, defaultValue?: string[]) => {
|
|
17
|
+
sumBy: string[] | undefined;
|
|
18
|
+
setSumBy: (sumBy: string[]) => void;
|
|
19
|
+
isLoading: boolean;
|
|
20
|
+
};
|
|
14
21
|
//# sourceMappingURL=useSumBy.d.ts.map
|
package/dist/useSumBy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../src/useSumBy.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../src/useSumBy.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAAO,CAAC;AA6BjD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,EAC5B,oBAEG;IACD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,KACL,CACD,MAAM,EAAE,GAAG,SAAS,EACpB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EAC1B;IACE,SAAS,EAAE,OAAO,CAAC;CACpB,CA+DF,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,KAC3B;IAAC,YAAY,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAMzD,CAAC;AAyBF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EAAE,GAAG,SAMpF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAU9E,CAAC;AAGF,eAAO,MAAM,QAAQ,GACnB,aAAa,kBAAkB,EAC/B,aAAa,WAAW,GAAG,SAAS,EACpC,WAAW,aAAa,EACxB,eAAe,MAAM,EAAE,KACtB;IACD,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;CAyBpB,CAAC"}
|
package/dist/useSumBy.js
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
13
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
|
+
import { useLabelNames } from './MatchersInput/index';
|
|
14
15
|
export const DEFAULT_EMPTY_SUM_BY = [];
|
|
15
16
|
const getDefaultSumBy = (profile, labels) => {
|
|
16
17
|
if (profile === undefined || labels === undefined) {
|
|
@@ -53,12 +54,23 @@ export const useSumBySelection = (profileType, labelNamesLoading, labels, { defa
|
|
|
53
54
|
});
|
|
54
55
|
}, [setUserSelectedSumBy, profileType]);
|
|
55
56
|
const { defaultSumBy } = useDefaultSumBy(profileType, labelNamesLoading, labels);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
// Store the last valid sumBy value to return during loading
|
|
58
|
+
const lastValidSumByRef = useRef(DEFAULT_EMPTY_SUM_BY);
|
|
59
|
+
const sumBy = useMemo(() => {
|
|
60
|
+
// If loading, return the last valid value to prevent input from blanking
|
|
61
|
+
if (labelNamesLoading && lastValidSumByRef.current !== DEFAULT_EMPTY_SUM_BY) {
|
|
62
|
+
return lastValidSumByRef.current;
|
|
63
|
+
}
|
|
64
|
+
let result = userSelectedSumBy[profileType?.toString() ?? ''] ?? defaultSumBy ?? DEFAULT_EMPTY_SUM_BY;
|
|
65
|
+
if (profileType?.delta !== true) {
|
|
66
|
+
result = DEFAULT_EMPTY_SUM_BY;
|
|
67
|
+
}
|
|
68
|
+
// Store the computed value for next loading state
|
|
69
|
+
lastValidSumByRef.current = result;
|
|
70
|
+
return result;
|
|
71
|
+
}, [userSelectedSumBy, profileType, defaultSumBy, labelNamesLoading]);
|
|
60
72
|
return [
|
|
61
|
-
|
|
73
|
+
sumBy,
|
|
62
74
|
setSumBy,
|
|
63
75
|
{
|
|
64
76
|
isLoading: labelNamesLoading,
|
|
@@ -105,3 +117,16 @@ export const sumByToParam = (sumBy) => {
|
|
|
105
117
|
}
|
|
106
118
|
return sumBy;
|
|
107
119
|
};
|
|
120
|
+
// Combined hook that handles all sumBy logic: fetching labels, computing defaults, and managing selection
|
|
121
|
+
export const useSumBy = (queryClient, profileType, timeRange, defaultValue) => {
|
|
122
|
+
const { loading: labelNamesLoading, result } = useLabelNames(queryClient, profileType?.toString() ?? '', timeRange.getFromMs(), timeRange.getToMs());
|
|
123
|
+
const labels = useMemo(() => {
|
|
124
|
+
return result.response?.labelNames === undefined ? [] : result.response.labelNames;
|
|
125
|
+
}, [result]);
|
|
126
|
+
const [sumBySelection, setSumByInternal, { isLoading }] = useSumBySelection(profileType, labelNamesLoading, labels, { defaultValue });
|
|
127
|
+
return {
|
|
128
|
+
sumBy: sumBySelection,
|
|
129
|
+
setSumBy: setSumByInternal,
|
|
130
|
+
isLoading,
|
|
131
|
+
};
|
|
132
|
+
};
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.74",
|
|
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
|
-
"@parca/client": "0.17.
|
|
10
|
-
"@parca/components": "0.16.
|
|
9
|
+
"@parca/client": "0.17.8",
|
|
10
|
+
"@parca/components": "0.16.381",
|
|
11
11
|
"@parca/dynamicsize": "0.16.67",
|
|
12
|
-
"@parca/hooks": "0.0.
|
|
12
|
+
"@parca/hooks": "0.0.108",
|
|
13
13
|
"@parca/icons": "0.16.74",
|
|
14
14
|
"@parca/parser": "0.16.81",
|
|
15
|
-
"@parca/store": "0.16.
|
|
15
|
+
"@parca/store": "0.16.191",
|
|
16
16
|
"@parca/test-utils": "0.0.17",
|
|
17
|
-
"@parca/utilities": "0.0.
|
|
17
|
+
"@parca/utilities": "0.0.114",
|
|
18
18
|
"@popperjs/core": "^2.11.8",
|
|
19
19
|
"@protobuf-ts/runtime-rpc": "^2.5.0",
|
|
20
20
|
"@storybook/preview-api": "^8.4.3",
|
|
@@ -79,5 +79,5 @@
|
|
|
79
79
|
"access": "public",
|
|
80
80
|
"registry": "https://registry.npmjs.org/"
|
|
81
81
|
},
|
|
82
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "6ca69bb6e4542edbc73ca635915b3ebae7a8e8c3"
|
|
83
83
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import React, {useMemo, useRef, useState} from 'react';
|
|
14
|
+
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {useQuery} from '@tanstack/react-query';
|
|
17
17
|
import cx from 'classnames';
|
|
@@ -78,7 +78,9 @@ export const useLabelNames = (
|
|
|
78
78
|
},
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
console.log('Label names query result:', {data, error, isLoading});
|
|
83
|
+
}, [data, error, isLoading]);
|
|
82
84
|
|
|
83
85
|
return {
|
|
84
86
|
result: {response: data, error: error as Error},
|
|
@@ -11,57 +11,87 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useState} from 'react';
|
|
14
|
+
import {useCallback, useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {QueryServiceClient} from '@parca/client';
|
|
17
|
-
import {
|
|
17
|
+
import {useURLStateBatch} from '@parca/components';
|
|
18
18
|
import {Query} from '@parca/parser';
|
|
19
19
|
import {TEST_IDS, testId} from '@parca/test-utils';
|
|
20
20
|
import type {NavigateFunction} from '@parca/utilities';
|
|
21
21
|
|
|
22
|
-
import {ProfileDiffSource,
|
|
23
|
-
import ProfileSelector
|
|
22
|
+
import {ProfileDiffSource, ProfileViewWithData} from '..';
|
|
23
|
+
import ProfileSelector from '../ProfileSelector';
|
|
24
|
+
import {useCompareModeMeta} from '../hooks/useCompareModeMeta';
|
|
25
|
+
import {useQueryState} from '../hooks/useQueryState';
|
|
24
26
|
|
|
25
27
|
interface ProfileExplorerCompareProps {
|
|
26
28
|
queryClient: QueryServiceClient;
|
|
27
|
-
|
|
28
|
-
queryA: QuerySelection;
|
|
29
|
-
queryB: QuerySelection;
|
|
30
|
-
profileA: ProfileSelection | null;
|
|
31
|
-
profileB: ProfileSelection | null;
|
|
32
|
-
selectQueryA: (query: QuerySelection) => void;
|
|
33
|
-
selectQueryB: (query: QuerySelection) => void;
|
|
34
|
-
selectProfileA: (source: ProfileSelection) => void;
|
|
35
|
-
selectProfileB: (source: ProfileSelection) => void;
|
|
36
|
-
closeProfile: (card: string) => void;
|
|
37
|
-
|
|
38
29
|
navigateTo: NavigateFunction;
|
|
39
30
|
}
|
|
40
31
|
|
|
41
32
|
const ProfileExplorerCompare = ({
|
|
42
33
|
queryClient,
|
|
43
|
-
queryA,
|
|
44
|
-
queryB,
|
|
45
|
-
profileA,
|
|
46
|
-
profileB,
|
|
47
|
-
selectQueryA,
|
|
48
|
-
selectQueryB,
|
|
49
|
-
selectProfileA,
|
|
50
|
-
selectProfileB,
|
|
51
|
-
closeProfile,
|
|
52
34
|
navigateTo,
|
|
53
35
|
}: ProfileExplorerCompareProps): JSX.Element => {
|
|
54
36
|
const [showMetricsGraph, setShowMetricsGraph] = useState(true);
|
|
37
|
+
const batchUpdates = useURLStateBatch();
|
|
38
|
+
const {closeCompareMode, isCompareMode, isCompareAbsolute} = useCompareModeMeta();
|
|
39
|
+
|
|
40
|
+
// Read ProfileSource states from URL for both sides
|
|
41
|
+
const {profileSource: profileSourceA, querySelection: querySelectionA} = useQueryState({
|
|
42
|
+
suffix: '_a',
|
|
43
|
+
comparing: true,
|
|
44
|
+
});
|
|
45
|
+
const {
|
|
46
|
+
profileSource: profileSourceB,
|
|
47
|
+
querySelection: querySelectionB,
|
|
48
|
+
commitDraft: commitDraftB,
|
|
49
|
+
setDraftExpression: setDraftExpressionB,
|
|
50
|
+
setDraftTimeRange: setDraftTimeRangeB,
|
|
51
|
+
} = useQueryState({suffix: '_b', comparing: true});
|
|
52
|
+
|
|
53
|
+
// Derive enforced profile name from side A's expression
|
|
54
|
+
const enforcedProfileNameA = useMemo(() => {
|
|
55
|
+
return querySelectionA.expression !== ''
|
|
56
|
+
? Query.parse(querySelectionA.expression).profileName()
|
|
57
|
+
: '';
|
|
58
|
+
}, [querySelectionA.expression]);
|
|
59
|
+
|
|
60
|
+
// Initialize side B with side A's values if side B is empty
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// If not in compare mode, don't initialize
|
|
63
|
+
if (!isCompareMode) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
if (querySelectionB.expression === '' && querySelectionA.expression !== '') {
|
|
68
|
+
batchUpdates(() => {
|
|
69
|
+
setDraftExpressionB(querySelectionA.expression);
|
|
70
|
+
setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection);
|
|
71
|
+
// Commit to update the URL and trigger metrics graph load
|
|
72
|
+
commitDraftB();
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}, [
|
|
76
|
+
isCompareMode,
|
|
77
|
+
querySelectionA.expression,
|
|
78
|
+
querySelectionA.from,
|
|
79
|
+
querySelectionA.to,
|
|
80
|
+
querySelectionA.timeSelection,
|
|
81
|
+
querySelectionB.expression,
|
|
82
|
+
setDraftExpressionB,
|
|
83
|
+
setDraftTimeRangeB,
|
|
84
|
+
commitDraftB,
|
|
85
|
+
batchUpdates,
|
|
86
|
+
]);
|
|
59
87
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
};
|
|
88
|
+
const closeProfileA = useCallback((): void => {
|
|
89
|
+
closeCompareMode('A');
|
|
90
|
+
}, [closeCompareMode]);
|
|
63
91
|
|
|
64
|
-
const
|
|
92
|
+
const closeProfileB = useCallback((): void => {
|
|
93
|
+
closeCompareMode('B');
|
|
94
|
+
}, [closeCompareMode]);
|
|
65
95
|
|
|
66
96
|
return (
|
|
67
97
|
<div {...testId(TEST_IDS.COMPARE_CONTAINER)}>
|
|
@@ -72,10 +102,6 @@ const ProfileExplorerCompare = ({
|
|
|
72
102
|
>
|
|
73
103
|
<ProfileSelector
|
|
74
104
|
queryClient={queryClient}
|
|
75
|
-
querySelection={queryA}
|
|
76
|
-
profileSelection={profileA}
|
|
77
|
-
selectProfile={selectProfileA}
|
|
78
|
-
selectQuery={selectQueryA}
|
|
79
105
|
closeProfile={closeProfileA}
|
|
80
106
|
enforcedProfileName={''}
|
|
81
107
|
comparing={true}
|
|
@@ -91,12 +117,8 @@ const ProfileExplorerCompare = ({
|
|
|
91
117
|
>
|
|
92
118
|
<ProfileSelector
|
|
93
119
|
queryClient={queryClient}
|
|
94
|
-
querySelection={queryB}
|
|
95
|
-
profileSelection={profileB}
|
|
96
|
-
selectProfile={selectProfileB}
|
|
97
|
-
selectQuery={selectQueryB}
|
|
98
120
|
closeProfile={closeProfileB}
|
|
99
|
-
enforcedProfileName={
|
|
121
|
+
enforcedProfileName={enforcedProfileNameA}
|
|
100
122
|
comparing={true}
|
|
101
123
|
navigateTo={navigateTo}
|
|
102
124
|
suffix="_b"
|
|
@@ -106,16 +128,12 @@ const ProfileExplorerCompare = ({
|
|
|
106
128
|
</div>
|
|
107
129
|
</div>
|
|
108
130
|
<div className="grid grid-cols-1">
|
|
109
|
-
{
|
|
131
|
+
{profileSourceA != null && profileSourceB != null ? (
|
|
110
132
|
<div {...testId(TEST_IDS.COMPARE_PROFILE_VIEW)}>
|
|
111
133
|
<ProfileViewWithData
|
|
112
134
|
queryClient={queryClient}
|
|
113
135
|
profileSource={
|
|
114
|
-
new ProfileDiffSource(
|
|
115
|
-
profileA.ProfileSource(),
|
|
116
|
-
profileB.ProfileSource(),
|
|
117
|
-
compareAbsolute === 'true'
|
|
118
|
-
)
|
|
136
|
+
new ProfileDiffSource(profileSourceA, profileSourceB, isCompareAbsolute)
|
|
119
137
|
}
|
|
120
138
|
/>
|
|
121
139
|
</div>
|
|
@@ -16,40 +16,30 @@ import {useState} from 'react';
|
|
|
16
16
|
import {QueryServiceClient} from '@parca/client';
|
|
17
17
|
import type {NavigateFunction} from '@parca/utilities';
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
import ProfileSelector
|
|
19
|
+
import {ProfileViewWithData} from '..';
|
|
20
|
+
import ProfileSelector from '../ProfileSelector';
|
|
21
|
+
import {useQueryState} from '../hooks/useQueryState';
|
|
21
22
|
|
|
22
23
|
interface ProfileExplorerSingleProps {
|
|
23
24
|
queryClient: QueryServiceClient;
|
|
24
|
-
query: QuerySelection;
|
|
25
|
-
selectQuery: (query: QuerySelection) => void;
|
|
26
|
-
selectProfile: (source: ProfileSelection) => void;
|
|
27
|
-
profile: ProfileSelection | null;
|
|
28
25
|
navigateTo: NavigateFunction;
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
const ProfileExplorerSingle = ({
|
|
32
29
|
queryClient,
|
|
33
|
-
query,
|
|
34
|
-
selectQuery,
|
|
35
|
-
selectProfile,
|
|
36
|
-
profile,
|
|
37
30
|
navigateTo,
|
|
38
31
|
}: ProfileExplorerSingleProps): JSX.Element => {
|
|
39
32
|
const [showMetricsGraph, setShowMetricsGraph] = useState(true);
|
|
33
|
+
const {profileSource} = useQueryState({suffix: '_a'});
|
|
40
34
|
|
|
41
35
|
return (
|
|
42
36
|
<>
|
|
43
37
|
<div className="relative">
|
|
44
38
|
<ProfileSelector
|
|
45
39
|
queryClient={queryClient}
|
|
46
|
-
querySelection={query}
|
|
47
|
-
selectQuery={selectQuery}
|
|
48
|
-
selectProfile={selectProfile}
|
|
49
40
|
closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
|
|
50
|
-
profileSelection={profile}
|
|
51
41
|
comparing={false}
|
|
52
|
-
enforcedProfileName={''}
|
|
42
|
+
enforcedProfileName={''}
|
|
53
43
|
navigateTo={navigateTo}
|
|
54
44
|
suffix="_a"
|
|
55
45
|
showMetricsGraph={showMetricsGraph}
|
|
@@ -57,10 +47,8 @@ const ProfileExplorerSingle = ({
|
|
|
57
47
|
/>
|
|
58
48
|
</div>
|
|
59
49
|
|
|
60
|
-
{
|
|
61
|
-
<ProfileViewWithData queryClient={queryClient} profileSource={
|
|
62
|
-
) : (
|
|
63
|
-
<></>
|
|
50
|
+
{profileSource != null && (
|
|
51
|
+
<ProfileViewWithData queryClient={queryClient} profileSource={profileSource} />
|
|
64
52
|
)}
|
|
65
53
|
</>
|
|
66
54
|
);
|