@parca/profile 0.17.2 → 0.17.4
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/GraphTooltipArrow/Content.d.ts +1 -2
- package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/Content.js +1 -2
- package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts +1 -2
- package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +1 -2
- package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts +1 -2
- package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/useGraphTooltip/index.js +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +2 -6
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +4 -5
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.d.ts +20 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.d.ts.map +1 -0
- package/{src/Callgraph/constants.ts → dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.js} +12 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts +8 -51
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.js +59 -136
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.d.ts +8 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.d.ts.map +1 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.js +40 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.d.ts +32 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.d.ts.map +1 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.js +40 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +4 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +62 -76
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.d.ts +3 -3
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.js +9 -7
- package/dist/ProfileIcicleGraph/index.d.ts +3 -6
- package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
- package/dist/ProfileIcicleGraph/index.js +8 -16
- package/dist/ProfileView/components/DashboardItems/index.d.ts +3 -5
- package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
- package/dist/ProfileView/components/DashboardItems/index.js +4 -9
- package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/index.js +1 -2
- package/dist/ProfileView/index.d.ts +1 -1
- package/dist/ProfileView/index.d.ts.map +1 -1
- package/dist/ProfileView/index.js +1 -13
- package/dist/ProfileView/types/visualization.d.ts +1 -1
- package/dist/ProfileView/types/visualization.d.ts.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/styles.css +1 -1
- package/package.json +5 -5
- package/src/GraphTooltipArrow/Content.tsx +0 -3
- package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +0 -3
- package/src/GraphTooltipArrow/useGraphTooltip/index.ts +1 -3
- package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +5 -13
- package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.tsx +53 -0
- package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.tsx +96 -310
- package/src/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.tsx +78 -0
- package/src/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.tsx +93 -0
- package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +110 -213
- package/src/ProfileIcicleGraph/IcicleGraphArrow/utils.ts +8 -15
- package/src/ProfileIcicleGraph/index.tsx +7 -36
- package/src/ProfileView/components/DashboardItems/index.tsx +2 -27
- package/src/ProfileView/components/Toolbars/index.tsx +0 -2
- package/src/ProfileView/index.tsx +0 -14
- package/src/ProfileView/types/visualization.ts +1 -1
- package/src/index.tsx +0 -5
- package/dist/Callgraph/constants.d.ts +0 -3
- package/dist/Callgraph/constants.d.ts.map +0 -1
- package/dist/Callgraph/constants.js +0 -14
- package/dist/Callgraph/index.d.ts +0 -11
- package/dist/Callgraph/index.d.ts.map +0 -1
- package/dist/Callgraph/index.js +0 -104
- package/dist/Callgraph/mockData/index.d.ts +0 -149
- package/dist/Callgraph/mockData/index.d.ts.map +0 -1
- package/dist/Callgraph/mockData/index.js +0 -594
- package/dist/Callgraph/utils.d.ts +0 -20
- package/dist/Callgraph/utils.d.ts.map +0 -1
- package/dist/Callgraph/utils.js +0 -97
- package/dist/GraphTooltip/ExpandOnHoverValue.d.ts +0 -7
- package/dist/GraphTooltip/ExpandOnHoverValue.d.ts.map +0 -1
- package/dist/GraphTooltip/ExpandOnHoverValue.js +0 -4
- package/dist/GraphTooltip/index.d.ts +0 -41
- package/dist/GraphTooltip/index.d.ts.map +0 -1
- package/dist/GraphTooltip/index.js +0 -201
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +0 -6
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.js +0 -59
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.d.ts +0 -47
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.js +0 -93
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -14
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/index.js +0 -48
- package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.d.ts +0 -15
- package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.js +0 -57
- package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.d.ts +0 -8
- package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.js +0 -32
- package/dist/ProfileIcicleGraph/IcicleGraph/utils.d.ts +0 -7
- package/dist/ProfileIcicleGraph/IcicleGraph/utils.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/utils.js +0 -66
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.d.ts +0 -9
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.d.ts.map +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.js +0 -45
- package/dist/ProfileView/hooks/useGraphviz.d.ts +0 -12
- package/dist/ProfileView/hooks/useGraphviz.d.ts.map +0 -1
- package/dist/ProfileView/hooks/useGraphviz.js +0 -42
- package/src/Callgraph/index.tsx +0 -177
- package/src/Callgraph/mockData/index.ts +0 -605
- package/src/Callgraph/utils.ts +0 -141
- package/src/GraphTooltip/ExpandOnHoverValue.tsx +0 -30
- package/src/GraphTooltip/index.tsx +0 -509
- package/src/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.tsx +0 -96
- package/src/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.tsx +0 -266
- package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +0 -123
- package/src/ProfileIcicleGraph/IcicleGraph/useColoredGraph.ts +0 -117
- package/src/ProfileIcicleGraph/IcicleGraph/useNodeColor.ts +0 -54
- package/src/ProfileIcicleGraph/IcicleGraph/utils.ts +0 -102
- package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.tsx +0 -130
- package/src/ProfileView/hooks/useGraphviz.ts +0 -69
|
@@ -1,96 +0,0 @@
|
|
|
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 {Icon} from '@iconify/react';
|
|
17
|
-
import cx from 'classnames';
|
|
18
|
-
|
|
19
|
-
import {useURLState} from '@parca/components';
|
|
20
|
-
import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
|
|
21
|
-
import {EVERYTHING_ELSE, selectStackColors, useAppSelector} from '@parca/store';
|
|
22
|
-
|
|
23
|
-
interface Props {
|
|
24
|
-
compareMode?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const ColorStackLegend = ({compareMode = false}: Props): JSX.Element => {
|
|
28
|
-
const [colorProfileName] = useUserPreference<string>(
|
|
29
|
-
USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
|
|
30
|
-
);
|
|
31
|
-
const [currentSearchString, setSearchString] = useURLState('search_string');
|
|
32
|
-
const stackColors = useAppSelector(selectStackColors);
|
|
33
|
-
|
|
34
|
-
const stackColorArray = useMemo(() => {
|
|
35
|
-
return Object.entries(stackColors).sort(([featureA], [featureB]) => {
|
|
36
|
-
if (featureA === EVERYTHING_ELSE) {
|
|
37
|
-
return 1;
|
|
38
|
-
}
|
|
39
|
-
if (featureB === EVERYTHING_ELSE) {
|
|
40
|
-
return -1;
|
|
41
|
-
}
|
|
42
|
-
return featureA?.localeCompare(featureB ?? '') ?? 0;
|
|
43
|
-
});
|
|
44
|
-
}, [stackColors]);
|
|
45
|
-
|
|
46
|
-
if (colorProfileName === 'default' || compareMode) {
|
|
47
|
-
return <></>;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<div className="my-6 flex flex-wrap justify-center gap-2">
|
|
52
|
-
{stackColorArray.map(([feature, color]) => {
|
|
53
|
-
const filteringAllowed = feature !== EVERYTHING_ELSE;
|
|
54
|
-
const isHighlighted = currentSearchString === feature;
|
|
55
|
-
return (
|
|
56
|
-
<div
|
|
57
|
-
key={feature}
|
|
58
|
-
className={cx('flex items-center justify-between gap-1 text-ellipsis p-1 pr-2', {
|
|
59
|
-
'cursor-pointer': filteringAllowed,
|
|
60
|
-
'bg-gray-200 dark:bg-gray-800': isHighlighted,
|
|
61
|
-
})}
|
|
62
|
-
onClick={() => {
|
|
63
|
-
if (!filteringAllowed) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (isHighlighted) {
|
|
67
|
-
setSearchString('');
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
setSearchString(feature);
|
|
71
|
-
}}
|
|
72
|
-
>
|
|
73
|
-
<div className="flex items-center">
|
|
74
|
-
<div
|
|
75
|
-
className="mr-1 inline-block h-4 w-4 rounded-[4px]"
|
|
76
|
-
style={{backgroundColor: color}}
|
|
77
|
-
/>
|
|
78
|
-
<span className="text-sm">{feature}</span>
|
|
79
|
-
</div>
|
|
80
|
-
{isHighlighted ? (
|
|
81
|
-
<Icon
|
|
82
|
-
icon="radix-icons:cross-circled"
|
|
83
|
-
onClick={e => {
|
|
84
|
-
setSearchString('');
|
|
85
|
-
e.stopPropagation();
|
|
86
|
-
}}
|
|
87
|
-
/>
|
|
88
|
-
) : null}
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
})}
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export default ColorStackLegend;
|
|
@@ -1,266 +0,0 @@
|
|
|
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 React, {useMemo} from 'react';
|
|
15
|
-
|
|
16
|
-
import cx from 'classnames';
|
|
17
|
-
|
|
18
|
-
import {FlamegraphNode} from '@parca/client';
|
|
19
|
-
import {
|
|
20
|
-
Location,
|
|
21
|
-
Mapping,
|
|
22
|
-
Function as ParcaFunction,
|
|
23
|
-
} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
24
|
-
import {useKeyDown} from '@parca/components';
|
|
25
|
-
import {selectBinaries, setHoveringNode, useAppDispatch, useAppSelector} from '@parca/store';
|
|
26
|
-
import {isSearchMatch, scaleLinear, type ScaleFunction} from '@parca/utilities';
|
|
27
|
-
|
|
28
|
-
import useNodeColor from './useNodeColor';
|
|
29
|
-
import {nodeLabel} from './utils';
|
|
30
|
-
|
|
31
|
-
export const RowHeight = 26;
|
|
32
|
-
|
|
33
|
-
interface IcicleGraphNodesProps {
|
|
34
|
-
data: FlamegraphNode[];
|
|
35
|
-
strings: string[];
|
|
36
|
-
mappings: Mapping[];
|
|
37
|
-
locations: Location[];
|
|
38
|
-
functions: ParcaFunction[];
|
|
39
|
-
x: number;
|
|
40
|
-
y: number;
|
|
41
|
-
total: bigint;
|
|
42
|
-
totalWidth: number;
|
|
43
|
-
level: number;
|
|
44
|
-
curPath: string[];
|
|
45
|
-
setCurPath: (path: string[]) => void;
|
|
46
|
-
path: string[];
|
|
47
|
-
xScale: ScaleFunction;
|
|
48
|
-
searchString?: string;
|
|
49
|
-
compareMode: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const IcicleGraphNodes = React.memo(function IcicleGraphNodesNoMemo({
|
|
53
|
-
data,
|
|
54
|
-
strings,
|
|
55
|
-
mappings,
|
|
56
|
-
locations,
|
|
57
|
-
functions,
|
|
58
|
-
x,
|
|
59
|
-
y,
|
|
60
|
-
xScale,
|
|
61
|
-
total,
|
|
62
|
-
totalWidth,
|
|
63
|
-
level,
|
|
64
|
-
path,
|
|
65
|
-
setCurPath,
|
|
66
|
-
curPath,
|
|
67
|
-
searchString,
|
|
68
|
-
compareMode,
|
|
69
|
-
}: IcicleGraphNodesProps): JSX.Element {
|
|
70
|
-
const binaries = useAppSelector(selectBinaries);
|
|
71
|
-
const nodes =
|
|
72
|
-
curPath.length === 0
|
|
73
|
-
? data
|
|
74
|
-
: data.filter(
|
|
75
|
-
d =>
|
|
76
|
-
d != null &&
|
|
77
|
-
curPath[0] ===
|
|
78
|
-
nodeLabel(d, strings, mappings, locations, functions, binaries.length > 1)
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<g transform={`translate(${x}, ${y})`}>
|
|
83
|
-
{nodes.map(function nodeMapper(d, i) {
|
|
84
|
-
const start = nodes.slice(0, i).reduce((sum, d) => sum + d.cumulative, 0n);
|
|
85
|
-
const xStart = xScale(start);
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<IcicleNode
|
|
89
|
-
key={`node-${level}-${i}`}
|
|
90
|
-
x={xStart}
|
|
91
|
-
y={0}
|
|
92
|
-
totalWidth={totalWidth}
|
|
93
|
-
height={RowHeight}
|
|
94
|
-
path={path}
|
|
95
|
-
setCurPath={setCurPath}
|
|
96
|
-
level={level}
|
|
97
|
-
curPath={curPath}
|
|
98
|
-
data={d}
|
|
99
|
-
strings={strings}
|
|
100
|
-
mappings={mappings}
|
|
101
|
-
locations={locations}
|
|
102
|
-
functions={functions}
|
|
103
|
-
total={total}
|
|
104
|
-
xScale={xScale}
|
|
105
|
-
searchString={searchString}
|
|
106
|
-
compareMode={compareMode}
|
|
107
|
-
/>
|
|
108
|
-
);
|
|
109
|
-
})}
|
|
110
|
-
</g>
|
|
111
|
-
);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
interface IcicleNodeProps {
|
|
115
|
-
x: number;
|
|
116
|
-
y: number;
|
|
117
|
-
height: number;
|
|
118
|
-
totalWidth: number;
|
|
119
|
-
curPath: string[];
|
|
120
|
-
level: number;
|
|
121
|
-
data: FlamegraphNode;
|
|
122
|
-
strings: string[];
|
|
123
|
-
mappings: Mapping[];
|
|
124
|
-
locations: Location[];
|
|
125
|
-
functions: ParcaFunction[];
|
|
126
|
-
path: string[];
|
|
127
|
-
total: bigint;
|
|
128
|
-
setCurPath: (path: string[]) => void;
|
|
129
|
-
xScale: ScaleFunction;
|
|
130
|
-
isRoot?: boolean;
|
|
131
|
-
searchString?: string;
|
|
132
|
-
compareMode: boolean;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const icicleRectStyles = {
|
|
136
|
-
cursor: 'pointer',
|
|
137
|
-
transition: 'opacity .15s linear',
|
|
138
|
-
};
|
|
139
|
-
const fadedIcicleRectStyles = {
|
|
140
|
-
cursor: 'pointer',
|
|
141
|
-
transition: 'opacity .15s linear',
|
|
142
|
-
opacity: '0.5',
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
export const IcicleNode = React.memo(function IcicleNodeNoMemo({
|
|
146
|
-
x,
|
|
147
|
-
y,
|
|
148
|
-
height,
|
|
149
|
-
setCurPath,
|
|
150
|
-
curPath,
|
|
151
|
-
level,
|
|
152
|
-
path,
|
|
153
|
-
data,
|
|
154
|
-
strings,
|
|
155
|
-
mappings,
|
|
156
|
-
locations,
|
|
157
|
-
functions,
|
|
158
|
-
total,
|
|
159
|
-
totalWidth,
|
|
160
|
-
xScale,
|
|
161
|
-
isRoot = false,
|
|
162
|
-
searchString,
|
|
163
|
-
compareMode,
|
|
164
|
-
}: IcicleNodeProps): JSX.Element {
|
|
165
|
-
const binaries = useAppSelector(selectBinaries);
|
|
166
|
-
const dispatch = useAppDispatch();
|
|
167
|
-
const {isShiftDown} = useKeyDown();
|
|
168
|
-
const colorResult = useNodeColor({data, compareMode});
|
|
169
|
-
const name = useMemo(() => {
|
|
170
|
-
return isRoot
|
|
171
|
-
? 'root'
|
|
172
|
-
: nodeLabel(data, strings, mappings, locations, functions, binaries.length > 1);
|
|
173
|
-
}, [data, strings, mappings, locations, functions, isRoot, binaries]);
|
|
174
|
-
const nextPath = path.concat([name]);
|
|
175
|
-
const isFaded = curPath.length > 0 && name !== curPath[curPath.length - 1];
|
|
176
|
-
const styles = isFaded ? fadedIcicleRectStyles : icicleRectStyles;
|
|
177
|
-
const nextLevel = level + 1;
|
|
178
|
-
const cumulative = data.cumulative;
|
|
179
|
-
const nextCurPath = curPath.length === 0 ? [] : curPath.slice(1);
|
|
180
|
-
const newXScale =
|
|
181
|
-
nextCurPath.length === 0 && curPath.length === 1
|
|
182
|
-
? scaleLinear([0n, cumulative], [0, totalWidth])
|
|
183
|
-
: xScale;
|
|
184
|
-
|
|
185
|
-
const width =
|
|
186
|
-
nextCurPath.length > 0 || (nextCurPath.length === 0 && curPath.length === 1)
|
|
187
|
-
? totalWidth
|
|
188
|
-
: xScale(cumulative);
|
|
189
|
-
|
|
190
|
-
const {isHighlightEnabled = false, isHighlighted = false} = useMemo(() => {
|
|
191
|
-
if (searchString === undefined || searchString === '') {
|
|
192
|
-
return {isHighlightEnabled: false};
|
|
193
|
-
}
|
|
194
|
-
return {isHighlightEnabled: true, isHighlighted: isSearchMatch(searchString, name)};
|
|
195
|
-
}, [searchString, name]);
|
|
196
|
-
|
|
197
|
-
if (width <= 1) {
|
|
198
|
-
return <>{null}</>;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const onMouseEnter = (): void => {
|
|
202
|
-
if (isShiftDown) return;
|
|
203
|
-
|
|
204
|
-
// need to add id and flat for tooltip purposes
|
|
205
|
-
dispatch(setHoveringNode({...data, id: '', flat: 0n}));
|
|
206
|
-
};
|
|
207
|
-
const onMouseLeave = (): void => {
|
|
208
|
-
if (isShiftDown) return;
|
|
209
|
-
|
|
210
|
-
dispatch(setHoveringNode(undefined));
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
<>
|
|
215
|
-
<g
|
|
216
|
-
transform={`translate(${x + 1}, ${y + 1})`}
|
|
217
|
-
style={styles}
|
|
218
|
-
onMouseEnter={onMouseEnter}
|
|
219
|
-
onMouseLeave={onMouseLeave}
|
|
220
|
-
onClick={() => {
|
|
221
|
-
setCurPath(nextPath);
|
|
222
|
-
}}
|
|
223
|
-
>
|
|
224
|
-
<rect
|
|
225
|
-
x={0}
|
|
226
|
-
y={0}
|
|
227
|
-
width={width}
|
|
228
|
-
height={height}
|
|
229
|
-
style={{
|
|
230
|
-
fill: colorResult,
|
|
231
|
-
}}
|
|
232
|
-
className={cx('stroke-white dark:stroke-gray-700', {
|
|
233
|
-
'opacity-50': isHighlightEnabled && !isHighlighted,
|
|
234
|
-
})}
|
|
235
|
-
/>
|
|
236
|
-
{width > 5 && (
|
|
237
|
-
<svg width={width - 5} height={height}>
|
|
238
|
-
<text x={5} y={15} style={{fontSize: '12px'}}>
|
|
239
|
-
{name}
|
|
240
|
-
</text>
|
|
241
|
-
</svg>
|
|
242
|
-
)}
|
|
243
|
-
</g>
|
|
244
|
-
{data.children !== undefined && data.children.length > 0 && (
|
|
245
|
-
<IcicleGraphNodes
|
|
246
|
-
data={data.children}
|
|
247
|
-
strings={strings}
|
|
248
|
-
mappings={mappings}
|
|
249
|
-
locations={locations}
|
|
250
|
-
functions={functions}
|
|
251
|
-
x={x}
|
|
252
|
-
y={RowHeight}
|
|
253
|
-
xScale={newXScale}
|
|
254
|
-
total={total}
|
|
255
|
-
totalWidth={totalWidth}
|
|
256
|
-
level={nextLevel}
|
|
257
|
-
path={nextPath}
|
|
258
|
-
curPath={nextCurPath}
|
|
259
|
-
setCurPath={setCurPath}
|
|
260
|
-
searchString={searchString}
|
|
261
|
-
compareMode={compareMode}
|
|
262
|
-
/>
|
|
263
|
-
)}
|
|
264
|
-
</>
|
|
265
|
-
);
|
|
266
|
-
});
|
|
@@ -1,123 +0,0 @@
|
|
|
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 {memo, useEffect, useMemo, useRef, useState} from 'react';
|
|
15
|
-
|
|
16
|
-
import {Flamegraph} from '@parca/client';
|
|
17
|
-
import {useURLState} from '@parca/components';
|
|
18
|
-
import {ProfileType} from '@parca/parser';
|
|
19
|
-
import {setHoveringNode, useAppDispatch} from '@parca/store';
|
|
20
|
-
import {scaleLinear, selectQueryParam} from '@parca/utilities';
|
|
21
|
-
|
|
22
|
-
import GraphTooltip from '../../GraphTooltip';
|
|
23
|
-
import {useProfileViewContext} from '../../ProfileView/context/ProfileViewContext';
|
|
24
|
-
import ColorStackLegend from './ColorStackLegend';
|
|
25
|
-
import {IcicleNode, RowHeight} from './IcicleGraphNodes';
|
|
26
|
-
import useColoredGraph from './useColoredGraph';
|
|
27
|
-
|
|
28
|
-
interface IcicleGraphProps {
|
|
29
|
-
graph: Flamegraph;
|
|
30
|
-
total: bigint;
|
|
31
|
-
filtered: bigint;
|
|
32
|
-
profileType?: ProfileType;
|
|
33
|
-
width?: number;
|
|
34
|
-
curPath: string[];
|
|
35
|
-
setCurPath: (path: string[]) => void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const IcicleGraph = memo(function IcicleGraph({
|
|
39
|
-
graph,
|
|
40
|
-
total,
|
|
41
|
-
filtered,
|
|
42
|
-
width,
|
|
43
|
-
setCurPath,
|
|
44
|
-
curPath,
|
|
45
|
-
profileType,
|
|
46
|
-
}: IcicleGraphProps): JSX.Element {
|
|
47
|
-
const dispatch = useAppDispatch();
|
|
48
|
-
const [height, setHeight] = useState(0);
|
|
49
|
-
const svg = useRef(null);
|
|
50
|
-
const ref = useRef<SVGGElement>(null);
|
|
51
|
-
|
|
52
|
-
const coloredGraph = useColoredGraph(graph);
|
|
53
|
-
const [currentSearchString] = useURLState('search_string');
|
|
54
|
-
const {compareMode} = useProfileViewContext();
|
|
55
|
-
const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
|
|
56
|
-
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
if (ref.current != null) {
|
|
59
|
-
setHeight(ref?.current.getBoundingClientRect().height);
|
|
60
|
-
}
|
|
61
|
-
}, [width, coloredGraph]);
|
|
62
|
-
|
|
63
|
-
const xScale = useMemo(() => {
|
|
64
|
-
if (width === undefined) {
|
|
65
|
-
return scaleLinear([0n, total], [0, 1]);
|
|
66
|
-
}
|
|
67
|
-
return scaleLinear([0n, total], [0, width]);
|
|
68
|
-
}, [total, width]);
|
|
69
|
-
|
|
70
|
-
if (coloredGraph.root === undefined || width === undefined) {
|
|
71
|
-
return <></>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<div onMouseLeave={() => dispatch(setHoveringNode(undefined))}>
|
|
76
|
-
{isColorStackLegendEnabled && <ColorStackLegend compareMode={compareMode} />}
|
|
77
|
-
<GraphTooltip
|
|
78
|
-
unit={profileType?.sampleUnit ?? ''}
|
|
79
|
-
total={total}
|
|
80
|
-
totalUnfiltered={total + filtered}
|
|
81
|
-
contextElement={svg.current}
|
|
82
|
-
strings={coloredGraph.stringTable}
|
|
83
|
-
mappings={coloredGraph.mapping}
|
|
84
|
-
locations={coloredGraph.locations}
|
|
85
|
-
functions={coloredGraph.function}
|
|
86
|
-
/>
|
|
87
|
-
<svg
|
|
88
|
-
className="font-robotoMono"
|
|
89
|
-
width={width}
|
|
90
|
-
height={height}
|
|
91
|
-
preserveAspectRatio="xMinYMid"
|
|
92
|
-
ref={svg}
|
|
93
|
-
>
|
|
94
|
-
<g ref={ref}>
|
|
95
|
-
<g transform={'translate(0, 0)'}>
|
|
96
|
-
<IcicleNode
|
|
97
|
-
x={0}
|
|
98
|
-
y={0}
|
|
99
|
-
totalWidth={width}
|
|
100
|
-
height={RowHeight}
|
|
101
|
-
setCurPath={setCurPath}
|
|
102
|
-
curPath={curPath}
|
|
103
|
-
data={coloredGraph.root}
|
|
104
|
-
strings={coloredGraph.stringTable}
|
|
105
|
-
mappings={coloredGraph.mapping}
|
|
106
|
-
locations={coloredGraph.locations}
|
|
107
|
-
functions={coloredGraph.function}
|
|
108
|
-
total={total}
|
|
109
|
-
xScale={xScale}
|
|
110
|
-
path={[]}
|
|
111
|
-
level={0}
|
|
112
|
-
isRoot={true}
|
|
113
|
-
searchString={currentSearchString as string}
|
|
114
|
-
compareMode={compareMode}
|
|
115
|
-
/>
|
|
116
|
-
</g>
|
|
117
|
-
</g>
|
|
118
|
-
</svg>
|
|
119
|
-
</div>
|
|
120
|
-
);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
export default IcicleGraph;
|
|
@@ -1,117 +0,0 @@
|
|
|
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 {useEffect, useMemo} from 'react';
|
|
15
|
-
|
|
16
|
-
import {Flamegraph, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
|
|
17
|
-
import {
|
|
18
|
-
Location,
|
|
19
|
-
Mapping,
|
|
20
|
-
Function as ParcaFunction,
|
|
21
|
-
} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
22
|
-
import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
|
|
23
|
-
import {
|
|
24
|
-
selectDarkMode,
|
|
25
|
-
setFeatures,
|
|
26
|
-
useAppDispatch,
|
|
27
|
-
useAppSelector,
|
|
28
|
-
type BinaryFeatureType,
|
|
29
|
-
type BinaryFeaturesMap,
|
|
30
|
-
} from '@parca/store';
|
|
31
|
-
import type {ColorProfileName} from '@parca/utilities';
|
|
32
|
-
|
|
33
|
-
import {extractFeature} from './utils';
|
|
34
|
-
|
|
35
|
-
export interface ColoredFlamegraphNode extends FlamegraphNode {
|
|
36
|
-
feature?: string;
|
|
37
|
-
children: ColoredFlamegraphNode[];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface ColoredFlamgraphRootNode extends FlamegraphRootNode {
|
|
41
|
-
feature?: string;
|
|
42
|
-
children: ColoredFlamegraphNode[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface ColoredFlamegraph extends Flamegraph {
|
|
46
|
-
root: ColoredFlamgraphRootNode;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const colorNodes = (
|
|
50
|
-
nodes: FlamegraphNode[] | undefined,
|
|
51
|
-
strings: string[],
|
|
52
|
-
mappings: Mapping[],
|
|
53
|
-
locations: Location[],
|
|
54
|
-
functions: ParcaFunction[],
|
|
55
|
-
features: {[key: string]: BinaryFeatureType}
|
|
56
|
-
): ColoredFlamegraphNode[] => {
|
|
57
|
-
if (nodes === undefined) {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
return nodes.map<ColoredFlamegraphNode>(node => {
|
|
61
|
-
const coloredNode: ColoredFlamegraphNode = {
|
|
62
|
-
...node,
|
|
63
|
-
};
|
|
64
|
-
if (node.children != null) {
|
|
65
|
-
coloredNode.children = colorNodes(
|
|
66
|
-
node.children,
|
|
67
|
-
strings,
|
|
68
|
-
mappings,
|
|
69
|
-
locations,
|
|
70
|
-
functions,
|
|
71
|
-
features
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
const feature = extractFeature(node, mappings, locations, strings);
|
|
75
|
-
coloredNode.feature = feature.name;
|
|
76
|
-
features[feature.name] = feature.type;
|
|
77
|
-
return coloredNode;
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const useColoredGraph = (graph: Flamegraph): ColoredFlamegraph => {
|
|
82
|
-
const dispatch = useAppDispatch();
|
|
83
|
-
const [colorProfile] = useUserPreference<ColorProfileName>(
|
|
84
|
-
USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
|
|
85
|
-
);
|
|
86
|
-
const isDarkMode = useAppSelector(selectDarkMode);
|
|
87
|
-
|
|
88
|
-
const [coloredGraph, features]: [ColoredFlamegraph, BinaryFeaturesMap] = useMemo(() => {
|
|
89
|
-
if (graph.root == null) {
|
|
90
|
-
return [graph as ColoredFlamegraph, {}];
|
|
91
|
-
}
|
|
92
|
-
const features: BinaryFeaturesMap = {};
|
|
93
|
-
const coloredGraph = {
|
|
94
|
-
...graph,
|
|
95
|
-
root: {
|
|
96
|
-
...graph.root,
|
|
97
|
-
children: colorNodes(
|
|
98
|
-
graph.root.children ?? [],
|
|
99
|
-
graph.stringTable,
|
|
100
|
-
graph.mapping,
|
|
101
|
-
graph.locations,
|
|
102
|
-
graph.function,
|
|
103
|
-
features
|
|
104
|
-
),
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
return [coloredGraph, features];
|
|
108
|
-
}, [graph]);
|
|
109
|
-
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
dispatch(setFeatures({features, colorProfileName: colorProfile, isDarkMode}));
|
|
112
|
-
}, [features, colorProfile, dispatch, isDarkMode]);
|
|
113
|
-
|
|
114
|
-
return coloredGraph;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export default useColoredGraph;
|
|
@@ -1,54 +0,0 @@
|
|
|
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 {
|
|
17
|
-
EVERYTHING_ELSE,
|
|
18
|
-
selectColorProfiles,
|
|
19
|
-
selectDarkMode,
|
|
20
|
-
selectStackColors,
|
|
21
|
-
useAppSelector,
|
|
22
|
-
} from '@parca/store';
|
|
23
|
-
import {diffColor} from '@parca/utilities';
|
|
24
|
-
|
|
25
|
-
import type {ColoredFlamegraphNode} from './useColoredGraph';
|
|
26
|
-
|
|
27
|
-
interface Props {
|
|
28
|
-
data: ColoredFlamegraphNode;
|
|
29
|
-
compareMode: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const useNodeColor = ({data, compareMode}: Props): string => {
|
|
33
|
-
const colors = useAppSelector(selectStackColors);
|
|
34
|
-
const isDarkMode = useAppSelector(selectDarkMode);
|
|
35
|
-
const colorProfiles = useAppSelector(selectColorProfiles);
|
|
36
|
-
|
|
37
|
-
const color: string = useMemo(() => {
|
|
38
|
-
if (compareMode) {
|
|
39
|
-
const diff = data.diff;
|
|
40
|
-
const cumulative = data.cumulative;
|
|
41
|
-
return diffColor(diff, cumulative, isDarkMode);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const color =
|
|
45
|
-
colors[data.feature ?? EVERYTHING_ELSE] ??
|
|
46
|
-
(!isDarkMode ? colorProfiles.default.colors[0][0] : colorProfiles.default.colors[0][1]);
|
|
47
|
-
|
|
48
|
-
return color;
|
|
49
|
-
}, [data, colors, isDarkMode, compareMode, colorProfiles]);
|
|
50
|
-
|
|
51
|
-
return color;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export default useNodeColor;
|