@parca/profile 0.16.131 → 0.16.132
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/GraphTooltip/index.d.ts +2 -2
- package/dist/GraphTooltip/index.js +12 -2
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +1 -2
- package/dist/ProfileExplorer/index.js +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.d.ts +1 -3
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.js +11 -10
- package/dist/ProfileIcicleGraph/IcicleGraph/index.js +4 -3
- package/package.json +4 -4
- package/src/GraphTooltip/index.tsx +20 -3
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +2 -3
- package/src/ProfileExplorer/index.tsx +8 -6
- package/src/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.tsx +8 -13
- package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +5 -8
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.132 (2023-03-07)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## [0.16.131](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.130...@parca/profile@0.16.131) (2023-03-06)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -5,7 +5,7 @@ interface GraphTooltipProps {
|
|
|
5
5
|
y?: number;
|
|
6
6
|
unit: string;
|
|
7
7
|
total: number;
|
|
8
|
-
hoveringNode
|
|
8
|
+
hoveringNode?: HoveringNode;
|
|
9
9
|
contextElement: Element | null;
|
|
10
10
|
isFixed?: boolean;
|
|
11
11
|
virtualContextElement?: boolean;
|
|
@@ -20,5 +20,5 @@ export interface HoveringNode extends CallgraphNode, FlamegraphRootNode, Flamegr
|
|
|
20
20
|
[key: string]: any;
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
-
declare const GraphTooltip: ({ x, y, unit, total, hoveringNode, contextElement, isFixed, virtualContextElement, strings, mappings, locations, functions, }: GraphTooltipProps) => JSX.Element;
|
|
23
|
+
declare const GraphTooltip: ({ x, y, unit, total, hoveringNode: hoveringNodeProp, contextElement, isFixed, virtualContextElement, strings, mappings, locations, functions, }: GraphTooltipProps) => JSX.Element;
|
|
24
24
|
export default GraphTooltip;
|
|
@@ -33,12 +33,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
33
33
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
34
34
|
// See the License for the specific language governing permissions and
|
|
35
35
|
// limitations under the License.
|
|
36
|
-
import { useEffect, useState } from 'react';
|
|
36
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
37
37
|
import { pointer } from 'd3-selection';
|
|
38
38
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|
39
39
|
import { usePopper } from 'react-popper';
|
|
40
40
|
import { useKeyDown } from '@parca/components';
|
|
41
41
|
import { getLastItem, valueFormatter } from '@parca/functions';
|
|
42
|
+
import { selectHoveringNode, useAppSelector } from '@parca/store';
|
|
42
43
|
import { hexifyAddress, truncateString, truncateStringReverse } from '../';
|
|
43
44
|
import { ExpandOnHover } from './ExpandOnHoverValue';
|
|
44
45
|
var NoData = function () {
|
|
@@ -154,7 +155,16 @@ var GraphTooltipContent = function (_a) {
|
|
|
154
155
|
hoveringNode: hoveringNode, strings: strings, mappings: mappings, locations: locations, functions: functions })] }) }))] })) })), _jsx("span", __assign({ className: "block text-gray-500 text-xs mx-2" }, { children: isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.' }))] })) })) })));
|
|
155
156
|
};
|
|
156
157
|
var GraphTooltip = function (_a) {
|
|
157
|
-
var x = _a.x, y = _a.y, unit = _a.unit, total = _a.total,
|
|
158
|
+
var x = _a.x, y = _a.y, unit = _a.unit, total = _a.total, hoveringNodeProp = _a.hoveringNode, contextElement = _a.contextElement, _b = _a.isFixed, isFixed = _b === void 0 ? false : _b, _c = _a.virtualContextElement, virtualContextElement = _c === void 0 ? true : _c, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions;
|
|
159
|
+
var hoveringNodeState = useAppSelector(selectHoveringNode);
|
|
160
|
+
var hoveringNode = useMemo(function () {
|
|
161
|
+
var h = (hoveringNodeProp !== null && hoveringNodeProp !== void 0 ? hoveringNodeProp : hoveringNodeState);
|
|
162
|
+
if (h == null) {
|
|
163
|
+
return h;
|
|
164
|
+
}
|
|
165
|
+
// Cloning the object to avoid the mutating error as this is Redux store object and we are modifying the meta object in GraphTooltipContent component.
|
|
166
|
+
return __assign(__assign({}, h), { meta: __assign({}, h.meta) });
|
|
167
|
+
}, [hoveringNodeProp, hoveringNodeState]);
|
|
158
168
|
var _d = useState(null), popperElement = _d[0], setPopperElement = _d[1];
|
|
159
169
|
var _e = usePopper(virtualContextElement ? virtualElement : contextElement, popperElement, {
|
|
160
170
|
placement: 'bottom-start',
|
|
@@ -10,11 +10,10 @@ var __assign = (this && this.__assign) || function () {
|
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { KeyDownProvider } from '@parca/components';
|
|
14
13
|
import { ProfileViewWithData } from '..';
|
|
15
14
|
import ProfileSelector from '../ProfileSelector';
|
|
16
15
|
var ProfileExplorerSingle = function (_a) {
|
|
17
16
|
var queryClient = _a.queryClient, query = _a.query, selectQuery = _a.selectQuery, selectProfile = _a.selectProfile, profile = _a.profile, compareProfile = _a.compareProfile, navigateTo = _a.navigateTo;
|
|
18
|
-
return (_jsxs(
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", __assign({ className: "grid grid-cols-1" }, { children: _jsx("div", { children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: query, selectQuery: selectQuery, selectProfile: selectProfile, closeProfile: function () { }, profileSelection: profile, comparing: false, onCompareProfile: compareProfile, enforcedProfileName: '' }) }) })), _jsx("div", __assign({ className: "grid grid-cols-1" }, { children: _jsx("div", { children: profile != null ? (_jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: profile.ProfileSource(), navigateTo: navigateTo })) : (_jsx(_Fragment, {})) }) }))] }));
|
|
19
18
|
};
|
|
20
19
|
export default ProfileExplorerSingle;
|
|
@@ -24,7 +24,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
24
24
|
// limitations under the License.
|
|
25
25
|
import { useEffect, useState } from 'react';
|
|
26
26
|
import { Provider } from 'react-redux';
|
|
27
|
-
import { DateTimeRange, useParcaContext } from '@parca/components';
|
|
27
|
+
import { DateTimeRange, KeyDownProvider, useParcaContext } from '@parca/components';
|
|
28
28
|
import { store } from '@parca/store';
|
|
29
29
|
import { ProfileSelectionFromParams, SuffixParams } from '..';
|
|
30
30
|
import { useProfileTypes } from '../ProfileSelector';
|
|
@@ -201,6 +201,6 @@ var ProfileExplorerApp = function (_a) {
|
|
|
201
201
|
var ProfileExplorer = function (_a) {
|
|
202
202
|
var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
|
|
203
203
|
var reduxStore = store().store;
|
|
204
|
-
return (_jsx(Provider, __assign({ store: reduxStore }, { children: _jsx(ProfileExplorerApp, { queryClient: queryClient, queryParams: queryParams, navigateTo: navigateTo }) })));
|
|
204
|
+
return (_jsx(Provider, __assign({ store: reduxStore }, { children: _jsx(KeyDownProvider, { children: _jsx(ProfileExplorerApp, { queryClient: queryClient, queryParams: queryParams, navigateTo: navigateTo }) }) })));
|
|
205
205
|
};
|
|
206
206
|
export default ProfileExplorer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { FlamegraphNode
|
|
2
|
+
import { FlamegraphNode } from '@parca/client';
|
|
3
3
|
import { Location, Mapping, Function as ParcaFunction } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
4
4
|
export declare const RowHeight = 26;
|
|
5
5
|
interface IcicleGraphNodesProps {
|
|
@@ -15,7 +15,6 @@ interface IcicleGraphNodesProps {
|
|
|
15
15
|
level: number;
|
|
16
16
|
curPath: string[];
|
|
17
17
|
setCurPath: (path: string[]) => void;
|
|
18
|
-
setHoveringNode: (node: FlamegraphNode | FlamegraphRootNode | undefined) => void;
|
|
19
18
|
path: string[];
|
|
20
19
|
xScale: (value: number) => number;
|
|
21
20
|
searchString?: string;
|
|
@@ -37,7 +36,6 @@ interface IcicleNodeProps {
|
|
|
37
36
|
path: string[];
|
|
38
37
|
total: number;
|
|
39
38
|
setCurPath: (path: string[]) => void;
|
|
40
|
-
setHoveringNode: (node: FlamegraphNode | FlamegraphRootNode | undefined) => void;
|
|
41
39
|
xScale: (value: number) => number;
|
|
42
40
|
isRoot?: boolean;
|
|
43
41
|
searchString?: string;
|
|
@@ -27,12 +27,12 @@ import cx from 'classnames';
|
|
|
27
27
|
import { scaleLinear } from 'd3-scale';
|
|
28
28
|
import { useKeyDown } from '@parca/components';
|
|
29
29
|
import { isSearchMatch } from '@parca/functions';
|
|
30
|
-
import { selectBinaries, useAppSelector } from '@parca/store';
|
|
30
|
+
import { selectBinaries, setHoveringNode, useAppDispatch, useAppSelector } from '@parca/store';
|
|
31
31
|
import useNodeColor from './useNodeColor';
|
|
32
32
|
import { nodeLabel } from './utils';
|
|
33
33
|
export var RowHeight = 26;
|
|
34
|
-
export var IcicleGraphNodes = React.memo(function
|
|
35
|
-
var data = _a.data, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, x = _a.x, y = _a.y, xScale = _a.xScale, total = _a.total, totalWidth = _a.totalWidth, level = _a.level,
|
|
34
|
+
export var IcicleGraphNodes = React.memo(function IcicleGraphNodesNoMemo(_a) {
|
|
35
|
+
var data = _a.data, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, x = _a.x, y = _a.y, xScale = _a.xScale, total = _a.total, totalWidth = _a.totalWidth, level = _a.level, path = _a.path, setCurPath = _a.setCurPath, curPath = _a.curPath, searchString = _a.searchString, compareMode = _a.compareMode;
|
|
36
36
|
var binaries = useAppSelector(selectBinaries);
|
|
37
37
|
var nodes = curPath.length === 0
|
|
38
38
|
? data
|
|
@@ -41,10 +41,10 @@ export var IcicleGraphNodes = React.memo(function IcicleGraphNodes(_a) {
|
|
|
41
41
|
curPath[0] ===
|
|
42
42
|
nodeLabel(d, strings, mappings, locations, functions, binaries.length > 1);
|
|
43
43
|
});
|
|
44
|
-
return (_jsx("g", __assign({ transform: "translate(".concat(x, ", ").concat(y, ")") }, { children: nodes.map(function (d, i) {
|
|
44
|
+
return (_jsx("g", __assign({ transform: "translate(".concat(x, ", ").concat(y, ")") }, { children: nodes.map(function nodeMapper(d, i) {
|
|
45
45
|
var start = nodes.slice(0, i).reduce(function (sum, d) { return sum + parseFloat(d.cumulative); }, 0);
|
|
46
46
|
var xStart = xScale(start);
|
|
47
|
-
return (_jsx(IcicleNode, { x: xStart, y: 0, totalWidth: totalWidth, height: RowHeight, path: path, setCurPath: setCurPath,
|
|
47
|
+
return (_jsx(IcicleNode, { x: xStart, y: 0, totalWidth: totalWidth, height: RowHeight, path: path, setCurPath: setCurPath, level: level, curPath: curPath, data: d, strings: strings, mappings: mappings, locations: locations, functions: functions, total: total, xScale: xScale, searchString: searchString, compareMode: compareMode }, "node-".concat(level, "-").concat(i)));
|
|
48
48
|
}) })));
|
|
49
49
|
});
|
|
50
50
|
var icicleRectStyles = {
|
|
@@ -56,9 +56,10 @@ var fadedIcicleRectStyles = {
|
|
|
56
56
|
transition: 'opacity .15s linear',
|
|
57
57
|
opacity: '0.5',
|
|
58
58
|
};
|
|
59
|
-
export var IcicleNode = React.memo(function
|
|
60
|
-
var x = _a.x, y = _a.y, height = _a.height, setCurPath = _a.setCurPath,
|
|
59
|
+
export var IcicleNode = React.memo(function IcicleNodeNoMemo(_a) {
|
|
60
|
+
var x = _a.x, y = _a.y, height = _a.height, setCurPath = _a.setCurPath, curPath = _a.curPath, level = _a.level, path = _a.path, data = _a.data, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, total = _a.total, totalWidth = _a.totalWidth, xScale = _a.xScale, _b = _a.isRoot, isRoot = _b === void 0 ? false : _b, searchString = _a.searchString, compareMode = _a.compareMode;
|
|
61
61
|
var binaries = useAppSelector(selectBinaries);
|
|
62
|
+
var dispatch = useAppDispatch();
|
|
62
63
|
var isShiftDown = useKeyDown().isShiftDown;
|
|
63
64
|
var colorResult = useNodeColor({ data: data, compareMode: compareMode });
|
|
64
65
|
var name = useMemo(function () {
|
|
@@ -90,12 +91,12 @@ export var IcicleNode = React.memo(function IcicleNode(_a) {
|
|
|
90
91
|
var onMouseEnter = function () {
|
|
91
92
|
if (isShiftDown)
|
|
92
93
|
return;
|
|
93
|
-
setHoveringNode(data);
|
|
94
|
+
dispatch(setHoveringNode(data));
|
|
94
95
|
};
|
|
95
96
|
var onMouseLeave = function () {
|
|
96
97
|
if (isShiftDown)
|
|
97
98
|
return;
|
|
98
|
-
setHoveringNode(undefined);
|
|
99
|
+
dispatch(setHoveringNode(undefined));
|
|
99
100
|
};
|
|
100
101
|
return (_jsxs(_Fragment, { children: [_jsxs("g", __assign({ transform: "translate(".concat(x + 1, ", ").concat(y + 1, ")"), style: styles, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: function () {
|
|
101
102
|
setCurPath(nextPath);
|
|
@@ -103,5 +104,5 @@ export var IcicleNode = React.memo(function IcicleNode(_a) {
|
|
|
103
104
|
fill: colorResult,
|
|
104
105
|
}, className: cx('stroke-white dark:stroke-gray-700', {
|
|
105
106
|
'opacity-50': isHighlightEnabled && !isHighlighted,
|
|
106
|
-
}) }), width > 5 && (_jsx("svg", __assign({ width: width - 5, height: height }, { children: _jsx("text", __assign({ x: 5, y: 15, style: { fontSize: '12px' } }, { children: name })) })))] })), data.children !== undefined && data.children.length > 0 && (_jsx(IcicleGraphNodes, { data: data.children, strings: strings, mappings: mappings, locations: locations, functions: functions, x: x, y: RowHeight, xScale: newXScale, total: total, totalWidth: totalWidth, level: nextLevel,
|
|
107
|
+
}) }), width > 5 && (_jsx("svg", __assign({ width: width - 5, height: height }, { children: _jsx("text", __assign({ x: 5, y: 15, style: { fontSize: '12px' } }, { children: name })) })))] })), data.children !== undefined && data.children.length > 0 && (_jsx(IcicleGraphNodes, { data: data.children, strings: strings, mappings: mappings, locations: locations, functions: functions, x: x, y: RowHeight, xScale: newXScale, total: total, totalWidth: totalWidth, level: nextLevel, path: nextPath, curPath: nextCurPath, setCurPath: setCurPath, searchString: searchString, compareMode: compareMode }))] }));
|
|
107
108
|
});
|
|
@@ -25,6 +25,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
25
25
|
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
|
26
26
|
import { scaleLinear } from 'd3-scale';
|
|
27
27
|
import { selectQueryParam } from '@parca/functions';
|
|
28
|
+
import { setHoveringNode, useAppDispatch } from '@parca/store';
|
|
28
29
|
import GraphTooltip from '../../GraphTooltip';
|
|
29
30
|
import ColorStackLegend from './ColorStackLegend';
|
|
30
31
|
import { IcicleNode, RowHeight } from './IcicleGraphNodes';
|
|
@@ -32,8 +33,8 @@ import useColoredGraph from './useColoredGraph';
|
|
|
32
33
|
export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
33
34
|
var _b;
|
|
34
35
|
var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo;
|
|
35
|
-
var
|
|
36
|
-
var
|
|
36
|
+
var dispatch = useAppDispatch();
|
|
37
|
+
var _c = useState(0), height = _c[0], setHeight = _c[1];
|
|
37
38
|
var svg = useRef(null);
|
|
38
39
|
var ref = useRef(null);
|
|
39
40
|
var coloredGraph = useColoredGraph(graph);
|
|
@@ -54,6 +55,6 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
|
54
55
|
if (coloredGraph.root === undefined || width === undefined) {
|
|
55
56
|
return _jsx(_Fragment, {});
|
|
56
57
|
}
|
|
57
|
-
return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total,
|
|
58
|
+
return (_jsxs("div", __assign({ onMouseLeave: function () { return dispatch(setHoveringNode(undefined)); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total, contextElement: svg.current, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function }), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx("g", __assign({ transform: 'translate(0, 0)' }, { children: _jsx(IcicleNode, { x: 0, y: 0, totalWidth: width, height: RowHeight, setCurPath: setCurPath, curPath: curPath, data: coloredGraph.root, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function, total: total, xScale: xScale, path: [], level: 0, isRoot: true, searchString: currentSearchString, compareMode: compareMode }) })) })) }))] })));
|
|
58
59
|
});
|
|
59
60
|
export default IcicleGraph;
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.132",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@parca/client": "^0.16.65",
|
|
7
|
-
"@parca/components": "^0.16.
|
|
7
|
+
"@parca/components": "^0.16.107",
|
|
8
8
|
"@parca/dynamicsize": "^0.16.54",
|
|
9
9
|
"@parca/functions": "^0.16.66",
|
|
10
10
|
"@parca/parser": "^0.16.55",
|
|
11
|
-
"@parca/store": "^0.16.
|
|
11
|
+
"@parca/store": "^0.16.63",
|
|
12
12
|
"@types/react-beautiful-dnd": "^13.1.3",
|
|
13
13
|
"d3": "7.8.2",
|
|
14
14
|
"d3-scale": "^4.0.2",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"access": "public",
|
|
46
46
|
"registry": "https://registry.npmjs.org/"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "dd55ee1fb7a1a7393433738765a0cfe488cdd1cd"
|
|
49
49
|
}
|
|
@@ -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 {useEffect, useState} from 'react';
|
|
14
|
+
import {useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {pointer} from 'd3-selection';
|
|
17
17
|
import {CopyToClipboard} from 'react-copy-to-clipboard';
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
26
26
|
import {useKeyDown} from '@parca/components';
|
|
27
27
|
import {getLastItem, valueFormatter} from '@parca/functions';
|
|
28
|
+
import {selectHoveringNode, useAppSelector} from '@parca/store';
|
|
28
29
|
|
|
29
30
|
import {hexifyAddress, truncateString, truncateStringReverse} from '../';
|
|
30
31
|
import {ExpandOnHover} from './ExpandOnHoverValue';
|
|
@@ -38,7 +39,7 @@ interface GraphTooltipProps {
|
|
|
38
39
|
y?: number;
|
|
39
40
|
unit: string;
|
|
40
41
|
total: number;
|
|
41
|
-
hoveringNode
|
|
42
|
+
hoveringNode?: HoveringNode;
|
|
42
43
|
contextElement: Element | null;
|
|
43
44
|
isFixed?: boolean;
|
|
44
45
|
virtualContextElement?: boolean;
|
|
@@ -360,7 +361,7 @@ const GraphTooltip = ({
|
|
|
360
361
|
y,
|
|
361
362
|
unit,
|
|
362
363
|
total,
|
|
363
|
-
hoveringNode,
|
|
364
|
+
hoveringNode: hoveringNodeProp,
|
|
364
365
|
contextElement,
|
|
365
366
|
isFixed = false,
|
|
366
367
|
virtualContextElement = true,
|
|
@@ -369,6 +370,22 @@ const GraphTooltip = ({
|
|
|
369
370
|
locations,
|
|
370
371
|
functions,
|
|
371
372
|
}: GraphTooltipProps): JSX.Element => {
|
|
373
|
+
const hoveringNodeState = useAppSelector(selectHoveringNode);
|
|
374
|
+
const hoveringNode = useMemo<HoveringNode>(() => {
|
|
375
|
+
const h = (hoveringNodeProp ?? hoveringNodeState) as HoveringNode;
|
|
376
|
+
if (h == null) {
|
|
377
|
+
return h;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Cloning the object to avoid the mutating error as this is Redux store object and we are modifying the meta object in GraphTooltipContent component.
|
|
381
|
+
return {
|
|
382
|
+
...h,
|
|
383
|
+
meta: {
|
|
384
|
+
...h.meta,
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
}, [hoveringNodeProp, hoveringNodeState]);
|
|
388
|
+
|
|
372
389
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
373
390
|
|
|
374
391
|
const {styles, attributes, ...popperProps} = usePopper(
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
14
|
import {QueryServiceClient} from '@parca/client';
|
|
15
|
-
import {KeyDownProvider} from '@parca/components';
|
|
16
15
|
import type {NavigateFunction} from '@parca/functions';
|
|
17
16
|
|
|
18
17
|
import {ProfileSelection, ProfileViewWithData} from '..';
|
|
@@ -38,7 +37,7 @@ const ProfileExplorerSingle = ({
|
|
|
38
37
|
navigateTo,
|
|
39
38
|
}: ProfileExplorerSingleProps): JSX.Element => {
|
|
40
39
|
return (
|
|
41
|
-
|
|
40
|
+
<>
|
|
42
41
|
<div className="grid grid-cols-1">
|
|
43
42
|
<div>
|
|
44
43
|
<ProfileSelector
|
|
@@ -67,7 +66,7 @@ const ProfileExplorerSingle = ({
|
|
|
67
66
|
)}
|
|
68
67
|
</div>
|
|
69
68
|
</div>
|
|
70
|
-
|
|
69
|
+
</>
|
|
71
70
|
);
|
|
72
71
|
};
|
|
73
72
|
|
|
@@ -16,7 +16,7 @@ import {useEffect, useState} from 'react';
|
|
|
16
16
|
import {Provider} from 'react-redux';
|
|
17
17
|
|
|
18
18
|
import {QueryServiceClient} from '@parca/client';
|
|
19
|
-
import {DateTimeRange, useParcaContext} from '@parca/components';
|
|
19
|
+
import {DateTimeRange, KeyDownProvider, useParcaContext} from '@parca/components';
|
|
20
20
|
import type {NavigateFunction} from '@parca/functions';
|
|
21
21
|
import {store} from '@parca/store';
|
|
22
22
|
|
|
@@ -391,11 +391,13 @@ const ProfileExplorer = ({
|
|
|
391
391
|
|
|
392
392
|
return (
|
|
393
393
|
<Provider store={reduxStore}>
|
|
394
|
-
<
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
394
|
+
<KeyDownProvider>
|
|
395
|
+
<ProfileExplorerApp
|
|
396
|
+
queryClient={queryClient}
|
|
397
|
+
queryParams={queryParams}
|
|
398
|
+
navigateTo={navigateTo}
|
|
399
|
+
/>
|
|
400
|
+
</KeyDownProvider>
|
|
399
401
|
</Provider>
|
|
400
402
|
);
|
|
401
403
|
};
|
|
@@ -16,7 +16,7 @@ import React, {useMemo} from 'react';
|
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import {scaleLinear} from 'd3-scale';
|
|
18
18
|
|
|
19
|
-
import {FlamegraphNode
|
|
19
|
+
import {FlamegraphNode} from '@parca/client';
|
|
20
20
|
import {
|
|
21
21
|
Location,
|
|
22
22
|
Mapping,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
25
25
|
import {useKeyDown} from '@parca/components';
|
|
26
26
|
import {isSearchMatch} from '@parca/functions';
|
|
27
|
-
import {selectBinaries, useAppSelector} from '@parca/store';
|
|
27
|
+
import {selectBinaries, setHoveringNode, useAppDispatch, useAppSelector} from '@parca/store';
|
|
28
28
|
|
|
29
29
|
import useNodeColor from './useNodeColor';
|
|
30
30
|
import {nodeLabel} from './utils';
|
|
@@ -44,14 +44,13 @@ interface IcicleGraphNodesProps {
|
|
|
44
44
|
level: number;
|
|
45
45
|
curPath: string[];
|
|
46
46
|
setCurPath: (path: string[]) => void;
|
|
47
|
-
setHoveringNode: (node: FlamegraphNode | FlamegraphRootNode | undefined) => void;
|
|
48
47
|
path: string[];
|
|
49
48
|
xScale: (value: number) => number;
|
|
50
49
|
searchString?: string;
|
|
51
50
|
compareMode: boolean;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
export const IcicleGraphNodes = React.memo(function
|
|
53
|
+
export const IcicleGraphNodes = React.memo(function IcicleGraphNodesNoMemo({
|
|
55
54
|
data,
|
|
56
55
|
strings,
|
|
57
56
|
mappings,
|
|
@@ -63,7 +62,6 @@ export const IcicleGraphNodes = React.memo(function IcicleGraphNodes({
|
|
|
63
62
|
total,
|
|
64
63
|
totalWidth,
|
|
65
64
|
level,
|
|
66
|
-
setHoveringNode,
|
|
67
65
|
path,
|
|
68
66
|
setCurPath,
|
|
69
67
|
curPath,
|
|
@@ -83,7 +81,7 @@ export const IcicleGraphNodes = React.memo(function IcicleGraphNodes({
|
|
|
83
81
|
|
|
84
82
|
return (
|
|
85
83
|
<g transform={`translate(${x}, ${y})`}>
|
|
86
|
-
{nodes.map((d, i)
|
|
84
|
+
{nodes.map(function nodeMapper(d, i) {
|
|
87
85
|
const start = nodes.slice(0, i).reduce((sum, d) => sum + parseFloat(d.cumulative), 0);
|
|
88
86
|
const xStart = xScale(start);
|
|
89
87
|
|
|
@@ -96,7 +94,6 @@ export const IcicleGraphNodes = React.memo(function IcicleGraphNodes({
|
|
|
96
94
|
height={RowHeight}
|
|
97
95
|
path={path}
|
|
98
96
|
setCurPath={setCurPath}
|
|
99
|
-
setHoveringNode={setHoveringNode}
|
|
100
97
|
level={level}
|
|
101
98
|
curPath={curPath}
|
|
102
99
|
data={d}
|
|
@@ -130,7 +127,6 @@ interface IcicleNodeProps {
|
|
|
130
127
|
path: string[];
|
|
131
128
|
total: number;
|
|
132
129
|
setCurPath: (path: string[]) => void;
|
|
133
|
-
setHoveringNode: (node: FlamegraphNode | FlamegraphRootNode | undefined) => void;
|
|
134
130
|
xScale: (value: number) => number;
|
|
135
131
|
isRoot?: boolean;
|
|
136
132
|
searchString?: string;
|
|
@@ -147,12 +143,11 @@ const fadedIcicleRectStyles = {
|
|
|
147
143
|
opacity: '0.5',
|
|
148
144
|
};
|
|
149
145
|
|
|
150
|
-
export const IcicleNode = React.memo(function
|
|
146
|
+
export const IcicleNode = React.memo(function IcicleNodeNoMemo({
|
|
151
147
|
x,
|
|
152
148
|
y,
|
|
153
149
|
height,
|
|
154
150
|
setCurPath,
|
|
155
|
-
setHoveringNode,
|
|
156
151
|
curPath,
|
|
157
152
|
level,
|
|
158
153
|
path,
|
|
@@ -169,6 +164,7 @@ export const IcicleNode = React.memo(function IcicleNode({
|
|
|
169
164
|
compareMode,
|
|
170
165
|
}: IcicleNodeProps): JSX.Element {
|
|
171
166
|
const binaries = useAppSelector(selectBinaries);
|
|
167
|
+
const dispatch = useAppDispatch();
|
|
172
168
|
const {isShiftDown} = useKeyDown();
|
|
173
169
|
const colorResult = useNodeColor({data, compareMode});
|
|
174
170
|
const name = useMemo(() => {
|
|
@@ -206,12 +202,12 @@ export const IcicleNode = React.memo(function IcicleNode({
|
|
|
206
202
|
const onMouseEnter = (): void => {
|
|
207
203
|
if (isShiftDown) return;
|
|
208
204
|
|
|
209
|
-
setHoveringNode(data);
|
|
205
|
+
dispatch(setHoveringNode(data));
|
|
210
206
|
};
|
|
211
207
|
const onMouseLeave = (): void => {
|
|
212
208
|
if (isShiftDown) return;
|
|
213
209
|
|
|
214
|
-
setHoveringNode(undefined);
|
|
210
|
+
dispatch(setHoveringNode(undefined));
|
|
215
211
|
};
|
|
216
212
|
|
|
217
213
|
return (
|
|
@@ -258,7 +254,6 @@ export const IcicleNode = React.memo(function IcicleNode({
|
|
|
258
254
|
total={total}
|
|
259
255
|
totalWidth={totalWidth}
|
|
260
256
|
level={nextLevel}
|
|
261
|
-
setHoveringNode={setHoveringNode}
|
|
262
257
|
path={nextPath}
|
|
263
258
|
curPath={nextCurPath}
|
|
264
259
|
setCurPath={setCurPath}
|
|
@@ -15,10 +15,11 @@ import {memo, useEffect, useMemo, useRef, useState} from 'react';
|
|
|
15
15
|
|
|
16
16
|
import {scaleLinear} from 'd3-scale';
|
|
17
17
|
|
|
18
|
-
import {Flamegraph
|
|
18
|
+
import {Flamegraph} from '@parca/client';
|
|
19
19
|
import {selectQueryParam, type NavigateFunction} from '@parca/functions';
|
|
20
|
+
import {setHoveringNode, useAppDispatch} from '@parca/store';
|
|
20
21
|
|
|
21
|
-
import GraphTooltip
|
|
22
|
+
import GraphTooltip from '../../GraphTooltip';
|
|
22
23
|
import ColorStackLegend from './ColorStackLegend';
|
|
23
24
|
import {IcicleNode, RowHeight} from './IcicleGraphNodes';
|
|
24
25
|
import useColoredGraph from './useColoredGraph';
|
|
@@ -40,9 +41,7 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
40
41
|
sampleUnit,
|
|
41
42
|
navigateTo,
|
|
42
43
|
}: IcicleGraphProps): JSX.Element {
|
|
43
|
-
const
|
|
44
|
-
FlamegraphNode | FlamegraphRootNode | undefined
|
|
45
|
-
>();
|
|
44
|
+
const dispatch = useAppDispatch();
|
|
46
45
|
const [height, setHeight] = useState(0);
|
|
47
46
|
const svg = useRef(null);
|
|
48
47
|
const ref = useRef<SVGGElement>(null);
|
|
@@ -71,12 +70,11 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
return (
|
|
74
|
-
<div onMouseLeave={() => setHoveringNode(undefined)}>
|
|
73
|
+
<div onMouseLeave={() => dispatch(setHoveringNode(undefined))}>
|
|
75
74
|
<ColorStackLegend navigateTo={navigateTo} compareMode={compareMode} />
|
|
76
75
|
<GraphTooltip
|
|
77
76
|
unit={sampleUnit}
|
|
78
77
|
total={total}
|
|
79
|
-
hoveringNode={hoveringNode as HoveringNode}
|
|
80
78
|
contextElement={svg.current}
|
|
81
79
|
strings={coloredGraph.stringTable}
|
|
82
80
|
mappings={coloredGraph.mapping}
|
|
@@ -98,7 +96,6 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
98
96
|
totalWidth={width}
|
|
99
97
|
height={RowHeight}
|
|
100
98
|
setCurPath={setCurPath}
|
|
101
|
-
setHoveringNode={setHoveringNode}
|
|
102
99
|
curPath={curPath}
|
|
103
100
|
data={coloredGraph.root}
|
|
104
101
|
strings={coloredGraph.stringTable}
|