@parca/profile 0.16.376 → 0.16.377
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/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +4 -18
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +1 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +2 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/useMappingList.d.ts +2 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/useMappingList.js +33 -0
- package/dist/ProfileIcicleGraph/index.d.ts +1 -1
- package/dist/ProfileIcicleGraph/index.js +11 -7
- package/package.json +2 -2
- package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +6 -23
- package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +3 -2
- package/src/ProfileIcicleGraph/IcicleGraphArrow/useMappingList.ts +42 -0
- package/src/ProfileIcicleGraph/index.tsx +13 -6
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.16.377](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.376...@parca/profile@0.16.377) (2024-05-30)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## 0.16.376 (2024-05-30)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -2,9 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { type NavigateFunction } from '@parca/utilities';
|
|
3
3
|
interface Props {
|
|
4
4
|
mappings?: string[];
|
|
5
|
-
|
|
5
|
+
loading?: boolean;
|
|
6
6
|
navigateTo?: NavigateFunction;
|
|
7
7
|
compareMode?: boolean;
|
|
8
8
|
}
|
|
9
|
-
declare const ColorStackLegend: ({ mappings, navigateTo, compareMode,
|
|
9
|
+
declare const ColorStackLegend: ({ mappings, navigateTo, compareMode, loading, }: Props) => React.JSX.Element;
|
|
10
10
|
export default ColorStackLegend;
|
|
@@ -17,9 +17,9 @@ import cx from 'classnames';
|
|
|
17
17
|
import { useURLState } from '@parca/components';
|
|
18
18
|
import { USER_PREFERENCES, useCurrentColorProfile, useUserPreference } from '@parca/hooks';
|
|
19
19
|
import { EVERYTHING_ELSE, selectDarkMode, useAppSelector } from '@parca/store';
|
|
20
|
-
import { getLastItem } from '@parca/utilities';
|
|
21
20
|
import { getMappingColors } from '.';
|
|
22
|
-
|
|
21
|
+
import useMappingList from './useMappingList';
|
|
22
|
+
const ColorStackLegend = ({ mappings, navigateTo, compareMode = false, loading, }) => {
|
|
23
23
|
const isDarkMode = useAppSelector(selectDarkMode);
|
|
24
24
|
const currentColorProfile = useCurrentColorProfile();
|
|
25
25
|
const [colorProfileName] = useUserPreference(USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key);
|
|
@@ -27,21 +27,7 @@ const ColorStackLegend = ({ mappings, navigateTo, compareMode = false, mappingsL
|
|
|
27
27
|
param: 'binary_frame_filter',
|
|
28
28
|
navigateTo,
|
|
29
29
|
});
|
|
30
|
-
const mappingsList =
|
|
31
|
-
if (mappings === undefined) {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
|
-
const list = mappings
|
|
35
|
-
?.map(mapping => {
|
|
36
|
-
return getLastItem(mapping);
|
|
37
|
-
})
|
|
38
|
-
.flat() ?? [];
|
|
39
|
-
// We add a EVERYTHING ELSE mapping to the list.
|
|
40
|
-
list.push('');
|
|
41
|
-
// We sort the mappings alphabetically to make sure that the order is always the same.
|
|
42
|
-
list.sort((a, b) => a.localeCompare(b));
|
|
43
|
-
return list;
|
|
44
|
-
}, [mappings]);
|
|
30
|
+
const mappingsList = useMappingList(mappings);
|
|
45
31
|
const mappingColors = useMemo(() => {
|
|
46
32
|
const colors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
|
|
47
33
|
return colors;
|
|
@@ -57,7 +43,7 @@ const ColorStackLegend = ({ mappings, navigateTo, compareMode = false, mappingsL
|
|
|
57
43
|
return featureA?.localeCompare(featureB ?? '') ?? 0;
|
|
58
44
|
});
|
|
59
45
|
}, [mappingColors]);
|
|
60
|
-
if (
|
|
46
|
+
if (stackColorArray.length === 0 && loading === false) {
|
|
61
47
|
return _jsx(_Fragment, {});
|
|
62
48
|
}
|
|
63
49
|
if (Object.entries(mappingColors).length === 0) {
|
|
@@ -31,6 +31,7 @@ interface IcicleGraphArrowProps {
|
|
|
31
31
|
sortBy: string;
|
|
32
32
|
flamegraphLoading: boolean;
|
|
33
33
|
isHalfScreen: boolean;
|
|
34
|
+
mappingsListFromMetadata: string[];
|
|
34
35
|
}
|
|
35
36
|
export declare const getMappingColors: (mappingsList: string[], isDarkMode: boolean, currentColorProfile: ColorConfig) => mappingColors;
|
|
36
37
|
export declare const IcicleGraphArrow: React.NamedExoticComponent<IcicleGraphArrowProps>;
|
|
@@ -49,7 +49,7 @@ export const getMappingColors = (mappingsList, isDarkMode, currentColorProfile)
|
|
|
49
49
|
});
|
|
50
50
|
return colors;
|
|
51
51
|
};
|
|
52
|
-
export const IcicleGraphArrow = memo(function IcicleGraphArrow({ arrow, total, filtered, width, setCurPath, curPath, profileType, navigateTo, sortBy, flamegraphLoading, }) {
|
|
52
|
+
export const IcicleGraphArrow = memo(function IcicleGraphArrow({ arrow, total, filtered, width, setCurPath, curPath, profileType, navigateTo, sortBy, flamegraphLoading, mappingsListFromMetadata, }) {
|
|
53
53
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
|
|
54
54
|
const dispatch = useAppDispatch();
|
|
55
55
|
const [highlightSimilarStacksPreference] = useUserPreference(USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key);
|
|
@@ -70,7 +70,6 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({ arrow, total, f
|
|
|
70
70
|
});
|
|
71
71
|
const currentSearchString = selectQueryParam('search_string') ?? '';
|
|
72
72
|
const { compareMode } = useProfileViewContext();
|
|
73
|
-
// const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
74
73
|
const currentColorProfile = useCurrentColorProfile();
|
|
75
74
|
const colorForSimilarNodes = currentColorProfile.colorForSimilarNodes;
|
|
76
75
|
const mappingsList = useMemo(() => {
|
|
@@ -137,7 +136,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({ arrow, total, f
|
|
|
137
136
|
return;
|
|
138
137
|
}
|
|
139
138
|
// first time hiding a binary
|
|
140
|
-
const newMappingsList =
|
|
139
|
+
const newMappingsList = mappingsListFromMetadata.filter(mapping => mapping !== binaryToRemove);
|
|
141
140
|
setBinaryFrameFilter(newMappingsList);
|
|
142
141
|
};
|
|
143
142
|
// useMemo for the root graph as it otherwise renders the whole graph if the hoveringRow changes.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2022 The Parca Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
import { useMemo } from 'react';
|
|
14
|
+
import { getLastItem } from '@parca/utilities';
|
|
15
|
+
const useMappingList = (mappings) => {
|
|
16
|
+
const mappingsList = useMemo(() => {
|
|
17
|
+
if (mappings === undefined) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const list = mappings
|
|
21
|
+
?.map(mapping => {
|
|
22
|
+
return getLastItem(mapping);
|
|
23
|
+
})
|
|
24
|
+
.flat() ?? [];
|
|
25
|
+
// We add a EVERYTHING ELSE mapping to the list.
|
|
26
|
+
list.push('');
|
|
27
|
+
// We sort the mappings alphabetically to make sure that the order is always the same.
|
|
28
|
+
list.sort((a, b) => a.localeCompare(b));
|
|
29
|
+
return list;
|
|
30
|
+
}, [mappings]);
|
|
31
|
+
return mappingsList;
|
|
32
|
+
};
|
|
33
|
+
export default useMappingList;
|
|
@@ -20,5 +20,5 @@ interface ProfileIcicleGraphProps {
|
|
|
20
20
|
mappings?: string[];
|
|
21
21
|
mappingsLoading?: boolean;
|
|
22
22
|
}
|
|
23
|
-
declare const ProfileIcicleGraph: ({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, navigateTo, loading, setActionButtons, error, width, isHalfScreen, mappings,
|
|
23
|
+
declare const ProfileIcicleGraph: ({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, navigateTo, loading, setActionButtons, error, width, isHalfScreen, mappings, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
24
24
|
export default ProfileIcicleGraph;
|
|
@@ -24,6 +24,7 @@ import SortBySelect from './ActionButtons/SortBySelect';
|
|
|
24
24
|
import IcicleGraph from './IcicleGraph';
|
|
25
25
|
import IcicleGraphArrow, { FIELD_FUNCTION_NAME } from './IcicleGraphArrow';
|
|
26
26
|
import ColorStackLegend from './IcicleGraphArrow/ColorStackLegend';
|
|
27
|
+
import useMappingList from './IcicleGraphArrow/useMappingList';
|
|
27
28
|
const numberFormatter = new Intl.NumberFormat('en-US');
|
|
28
29
|
const ErrorContent = ({ errorMessage }) => {
|
|
29
30
|
return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
|
|
@@ -77,11 +78,12 @@ const GroupAndSortActionButtons = ({ navigateTo }) => {
|
|
|
77
78
|
}, [groupBy, setGroupBy]);
|
|
78
79
|
return (_jsxs(_Fragment, { children: [_jsx(GroupByDropdown, { groupBy: groupBy, toggleGroupBy: toggleGroupBy }), _jsx(SortBySelect, { compareMode: compareMode, sortBy: storeSortBy, setSortBy: setStoreSortBy })] }));
|
|
79
80
|
};
|
|
80
|
-
const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, navigateTo, loading, setActionButtons, error, width, isHalfScreen, mappings,
|
|
81
|
+
const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, navigateTo, loading, setActionButtons, error, width, isHalfScreen, mappings, }) {
|
|
81
82
|
const { onError, authenticationErrorMessage, isDarkMode } = useParcaContext();
|
|
82
83
|
const { compareMode } = useProfileViewContext();
|
|
83
84
|
const [isLoading, setIsLoading] = useState(true);
|
|
84
85
|
const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
86
|
+
const mappingsList = useMappingList(mappings);
|
|
85
87
|
const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState({
|
|
86
88
|
param: 'sort_by',
|
|
87
89
|
navigateTo,
|
|
@@ -123,14 +125,15 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
123
125
|
isHalfScreen,
|
|
124
126
|
isLoading,
|
|
125
127
|
]);
|
|
128
|
+
const loadingState = !loading && (arrow !== undefined || graph !== undefined) && mappings !== undefined;
|
|
126
129
|
useEffect(() => {
|
|
127
|
-
if (
|
|
130
|
+
if (loadingState) {
|
|
128
131
|
setIsLoading(false);
|
|
129
132
|
}
|
|
130
133
|
else {
|
|
131
134
|
setIsLoading(true);
|
|
132
135
|
}
|
|
133
|
-
}, [
|
|
136
|
+
}, [loadingState]);
|
|
134
137
|
if (error != null) {
|
|
135
138
|
onError?.(error);
|
|
136
139
|
if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
|
|
@@ -150,26 +153,27 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
|
|
|
150
153
|
if (graph !== undefined)
|
|
151
154
|
return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, navigateTo: navigateTo }));
|
|
152
155
|
if (arrow !== undefined)
|
|
153
|
-
return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, navigateTo: navigateTo, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen }));
|
|
156
|
+
return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, navigateTo: navigateTo, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList }));
|
|
154
157
|
}, [
|
|
155
158
|
isLoading,
|
|
156
159
|
graph,
|
|
157
160
|
arrow,
|
|
158
161
|
total,
|
|
162
|
+
loading,
|
|
163
|
+
width,
|
|
159
164
|
filtered,
|
|
160
165
|
curPath,
|
|
161
166
|
setNewCurPath,
|
|
162
167
|
profileType,
|
|
163
168
|
navigateTo,
|
|
164
|
-
width,
|
|
165
169
|
storeSortBy,
|
|
166
170
|
isHalfScreen,
|
|
167
171
|
isDarkMode,
|
|
168
|
-
|
|
172
|
+
mappingsList,
|
|
169
173
|
]);
|
|
170
174
|
if (isTrimmed) {
|
|
171
175
|
console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
|
|
172
176
|
}
|
|
173
|
-
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, isColorStackLegendEnabled && (_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode, mappings: mappings,
|
|
177
|
+
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, isColorStackLegendEnabled && (_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode, mappings: mappings, loading: isLoading })), _jsx("div", { className: "min-h-48", id: "h-icicle-graph", children: _jsx(_Fragment, { children: icicleGraph }) }), _jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] })] }, "icicle-graph-loaded") }));
|
|
174
178
|
};
|
|
175
179
|
export default ProfileIcicleGraph;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.377",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@headlessui/react": "^1.7.19",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"access": "public",
|
|
72
72
|
"registry": "https://registry.npmjs.org/"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "7f48ce8d53a8f749508d0b002c04bf1257c4bbde"
|
|
75
75
|
}
|
|
@@ -19,13 +19,14 @@ import cx from 'classnames';
|
|
|
19
19
|
import {useURLState} from '@parca/components';
|
|
20
20
|
import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks';
|
|
21
21
|
import {EVERYTHING_ELSE, selectDarkMode, useAppSelector} from '@parca/store';
|
|
22
|
-
import {
|
|
22
|
+
import {type NavigateFunction} from '@parca/utilities';
|
|
23
23
|
|
|
24
24
|
import {getMappingColors} from '.';
|
|
25
|
+
import useMappingList from './useMappingList';
|
|
25
26
|
|
|
26
27
|
interface Props {
|
|
27
28
|
mappings?: string[];
|
|
28
|
-
|
|
29
|
+
loading?: boolean;
|
|
29
30
|
navigateTo?: NavigateFunction;
|
|
30
31
|
compareMode?: boolean;
|
|
31
32
|
}
|
|
@@ -34,7 +35,7 @@ const ColorStackLegend = ({
|
|
|
34
35
|
mappings,
|
|
35
36
|
navigateTo,
|
|
36
37
|
compareMode = false,
|
|
37
|
-
|
|
38
|
+
loading,
|
|
38
39
|
}: Props): React.JSX.Element => {
|
|
39
40
|
const isDarkMode = useAppSelector(selectDarkMode);
|
|
40
41
|
const currentColorProfile = useCurrentColorProfile();
|
|
@@ -46,25 +47,7 @@ const ColorStackLegend = ({
|
|
|
46
47
|
navigateTo,
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
const mappingsList =
|
|
50
|
-
if (mappings === undefined) {
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
const list =
|
|
54
|
-
mappings
|
|
55
|
-
?.map(mapping => {
|
|
56
|
-
return getLastItem(mapping) as string;
|
|
57
|
-
})
|
|
58
|
-
.flat() ?? [];
|
|
59
|
-
|
|
60
|
-
// We add a EVERYTHING ELSE mapping to the list.
|
|
61
|
-
list.push('');
|
|
62
|
-
|
|
63
|
-
// We sort the mappings alphabetically to make sure that the order is always the same.
|
|
64
|
-
list.sort((a, b) => a.localeCompare(b));
|
|
65
|
-
|
|
66
|
-
return list;
|
|
67
|
-
}, [mappings]);
|
|
50
|
+
const mappingsList = useMappingList(mappings);
|
|
68
51
|
|
|
69
52
|
const mappingColors = useMemo(() => {
|
|
70
53
|
const colors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
|
|
@@ -83,7 +66,7 @@ const ColorStackLegend = ({
|
|
|
83
66
|
});
|
|
84
67
|
}, [mappingColors]);
|
|
85
68
|
|
|
86
|
-
if (
|
|
69
|
+
if (stackColorArray.length === 0 && loading === false) {
|
|
87
70
|
return <></>;
|
|
88
71
|
}
|
|
89
72
|
|
|
@@ -72,6 +72,7 @@ interface IcicleGraphArrowProps {
|
|
|
72
72
|
sortBy: string;
|
|
73
73
|
flamegraphLoading: boolean;
|
|
74
74
|
isHalfScreen: boolean;
|
|
75
|
+
mappingsListFromMetadata: string[];
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export const getMappingColors = (
|
|
@@ -99,6 +100,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
|
|
|
99
100
|
navigateTo,
|
|
100
101
|
sortBy,
|
|
101
102
|
flamegraphLoading,
|
|
103
|
+
mappingsListFromMetadata,
|
|
102
104
|
}: IcicleGraphArrowProps): React.JSX.Element {
|
|
103
105
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
|
|
104
106
|
const dispatch = useAppDispatch();
|
|
@@ -126,7 +128,6 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
|
|
|
126
128
|
|
|
127
129
|
const currentSearchString = (selectQueryParam('search_string') as string) ?? '';
|
|
128
130
|
const {compareMode} = useProfileViewContext();
|
|
129
|
-
// const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
130
131
|
const currentColorProfile = useCurrentColorProfile();
|
|
131
132
|
const colorForSimilarNodes = currentColorProfile.colorForSimilarNodes;
|
|
132
133
|
|
|
@@ -209,7 +210,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
// first time hiding a binary
|
|
212
|
-
const newMappingsList =
|
|
213
|
+
const newMappingsList = mappingsListFromMetadata.filter(mapping => mapping !== binaryToRemove);
|
|
213
214
|
setBinaryFrameFilter(newMappingsList);
|
|
214
215
|
};
|
|
215
216
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright 2022 The Parca Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
|
|
14
|
+
import {useMemo} from 'react';
|
|
15
|
+
|
|
16
|
+
import {getLastItem} from '@parca/utilities';
|
|
17
|
+
|
|
18
|
+
const useMappingList = (mappings: string[] | undefined): string[] => {
|
|
19
|
+
const mappingsList = useMemo(() => {
|
|
20
|
+
if (mappings === undefined) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const list =
|
|
24
|
+
mappings
|
|
25
|
+
?.map(mapping => {
|
|
26
|
+
return getLastItem(mapping) as string;
|
|
27
|
+
})
|
|
28
|
+
.flat() ?? [];
|
|
29
|
+
|
|
30
|
+
// We add a EVERYTHING ELSE mapping to the list.
|
|
31
|
+
list.push('');
|
|
32
|
+
|
|
33
|
+
// We sort the mappings alphabetically to make sure that the order is always the same.
|
|
34
|
+
list.sort((a, b) => a.localeCompare(b));
|
|
35
|
+
|
|
36
|
+
return list;
|
|
37
|
+
}, [mappings]);
|
|
38
|
+
|
|
39
|
+
return mappingsList;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default useMappingList;
|
|
@@ -40,6 +40,7 @@ import SortBySelect from './ActionButtons/SortBySelect';
|
|
|
40
40
|
import IcicleGraph from './IcicleGraph';
|
|
41
41
|
import IcicleGraphArrow, {FIELD_FUNCTION_NAME} from './IcicleGraphArrow';
|
|
42
42
|
import ColorStackLegend from './IcicleGraphArrow/ColorStackLegend';
|
|
43
|
+
import useMappingList from './IcicleGraphArrow/useMappingList';
|
|
43
44
|
|
|
44
45
|
const numberFormatter = new Intl.NumberFormat('en-US');
|
|
45
46
|
|
|
@@ -220,13 +221,14 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
220
221
|
width,
|
|
221
222
|
isHalfScreen,
|
|
222
223
|
mappings,
|
|
223
|
-
mappingsLoading,
|
|
224
224
|
}: ProfileIcicleGraphProps): JSX.Element {
|
|
225
225
|
const {onError, authenticationErrorMessage, isDarkMode} = useParcaContext();
|
|
226
226
|
const {compareMode} = useProfileViewContext();
|
|
227
227
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
|
228
228
|
const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
229
229
|
|
|
230
|
+
const mappingsList = useMappingList(mappings);
|
|
231
|
+
|
|
230
232
|
const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState({
|
|
231
233
|
param: 'sort_by',
|
|
232
234
|
navigateTo,
|
|
@@ -327,13 +329,16 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
327
329
|
isLoading,
|
|
328
330
|
]);
|
|
329
331
|
|
|
332
|
+
const loadingState =
|
|
333
|
+
!loading && (arrow !== undefined || graph !== undefined) && mappings !== undefined;
|
|
334
|
+
|
|
330
335
|
useEffect(() => {
|
|
331
|
-
if (
|
|
336
|
+
if (loadingState) {
|
|
332
337
|
setIsLoading(false);
|
|
333
338
|
} else {
|
|
334
339
|
setIsLoading(true);
|
|
335
340
|
}
|
|
336
|
-
}, [
|
|
341
|
+
}, [loadingState]);
|
|
337
342
|
|
|
338
343
|
if (error != null) {
|
|
339
344
|
onError?.(error);
|
|
@@ -389,6 +394,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
389
394
|
sortBy={storeSortBy as string}
|
|
390
395
|
flamegraphLoading={isLoading}
|
|
391
396
|
isHalfScreen={isHalfScreen}
|
|
397
|
+
mappingsListFromMetadata={mappingsList}
|
|
392
398
|
/>
|
|
393
399
|
);
|
|
394
400
|
}, [
|
|
@@ -396,16 +402,17 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
396
402
|
graph,
|
|
397
403
|
arrow,
|
|
398
404
|
total,
|
|
405
|
+
loading,
|
|
406
|
+
width,
|
|
399
407
|
filtered,
|
|
400
408
|
curPath,
|
|
401
409
|
setNewCurPath,
|
|
402
410
|
profileType,
|
|
403
411
|
navigateTo,
|
|
404
|
-
width,
|
|
405
412
|
storeSortBy,
|
|
406
413
|
isHalfScreen,
|
|
407
414
|
isDarkMode,
|
|
408
|
-
|
|
415
|
+
mappingsList,
|
|
409
416
|
]);
|
|
410
417
|
|
|
411
418
|
if (isTrimmed) {
|
|
@@ -427,7 +434,7 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
427
434
|
navigateTo={navigateTo}
|
|
428
435
|
compareMode={compareMode}
|
|
429
436
|
mappings={mappings}
|
|
430
|
-
|
|
437
|
+
loading={isLoading}
|
|
431
438
|
/>
|
|
432
439
|
)}
|
|
433
440
|
<div className="min-h-48" id="h-icicle-graph">
|