@parca/profile 0.16.120 → 0.16.122
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/GraphTooltip/ExpandOnHoverValue.d.ts +6 -0
- package/dist/GraphTooltip/ExpandOnHoverValue.js +16 -0
- package/dist/GraphTooltip/index.d.ts +2 -2
- package/dist/GraphTooltip/index.js +40 -23
- package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.js +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +2 -2
- package/dist/ProfileIcicleGraph/IcicleGraph/index.js +3 -12
- package/dist/ProfileView/index.js +5 -2
- package/dist/styles.css +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +6 -0
- package/package.json +3 -3
- package/src/GraphTooltip/ExpandOnHoverValue.tsx +30 -0
- package/src/GraphTooltip/index.tsx +134 -110
- package/src/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.tsx +3 -3
- package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +1 -14
- package/src/ProfileView/index.tsx +18 -4
- package/src/utils.ts +8 -0
- package/tailwind.config.js +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.16.122](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.121...@parca/profile@0.16.122) (2023-02-22)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## 0.16.121 (2023-02-21)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## 0.16.120 (2023-02-21)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
export var ExpandOnHover = function (_a) {
|
|
14
|
+
var value = _a.value, displayValue = _a.displayValue;
|
|
15
|
+
return (_jsxs("div", __assign({ className: "relative group w-full" }, { children: [_jsx("div", __assign({ className: "text-ellipsis w-full overflow-hidden whitespace-nowrap" }, { children: displayValue !== null && displayValue !== void 0 ? displayValue : value })), _jsx("div", __assign({ className: "group-hover:flex hidden absolute -inset-2 max-w-[500px] whitespace-normal h-fit bg-gray-50 dark:bg-gray-900 shadow-[0_0_10px_2px_rgba(0,0,0,0.3)] rounded p-2 break-all" }, { children: value }))] })));
|
|
16
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CallgraphNode, FlamegraphNode, FlamegraphNodeMeta, FlamegraphRootNode } from '@parca/client';
|
|
2
2
|
import { Location, Mapping, Function as ParcaFunction } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
3
3
|
interface GraphTooltipProps {
|
|
4
|
-
x
|
|
5
|
-
y
|
|
4
|
+
x?: number;
|
|
5
|
+
y?: number;
|
|
6
6
|
unit: string;
|
|
7
7
|
total: number;
|
|
8
8
|
hoveringNode: HoveringNode;
|
|
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
20
20
|
}
|
|
21
21
|
return t;
|
|
22
22
|
};
|
|
23
|
-
import {
|
|
23
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
24
24
|
// Copyright 2022 The Parca Authors
|
|
25
25
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
26
26
|
// you may not use this file except in compliance with the License.
|
|
@@ -34,11 +34,16 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
34
34
|
// See the License for the specific language governing permissions and
|
|
35
35
|
// limitations under the License.
|
|
36
36
|
import { useEffect, useState } from 'react';
|
|
37
|
+
import { pointer } from 'd3-selection';
|
|
37
38
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|
38
39
|
import { usePopper } from 'react-popper';
|
|
39
40
|
import { useKeyDown } from '@parca/components';
|
|
40
41
|
import { getLastItem, valueFormatter } from '@parca/functions';
|
|
41
|
-
import { hexifyAddress, truncateString } from '../';
|
|
42
|
+
import { hexifyAddress, truncateString, truncateStringReverse } from '../';
|
|
43
|
+
import { ExpandOnHover } from './ExpandOnHoverValue';
|
|
44
|
+
var NoData = function () {
|
|
45
|
+
return _jsx("span", __assign({ className: "rounded bg-gray-200 dark:bg-gray-800 px-2" }, { children: "Not available" }));
|
|
46
|
+
};
|
|
42
47
|
var virtualElement = {
|
|
43
48
|
getBoundingClientRect: function () {
|
|
44
49
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -69,13 +74,11 @@ function generateGetBoundingClientRect(contextElement, x, y) {
|
|
|
69
74
|
};
|
|
70
75
|
}
|
|
71
76
|
var TooltipMetaInfo = function (_a) {
|
|
72
|
-
var _b, _c, _d, _e;
|
|
77
|
+
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
73
78
|
var hoveringNode = _a.hoveringNode, onCopy = _a.onCopy, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions;
|
|
74
|
-
if (hoveringNode.meta === undefined)
|
|
75
|
-
return _jsx(_Fragment, {});
|
|
76
79
|
// populate meta from the flamegraph metadata tables
|
|
77
80
|
if (locations !== undefined &&
|
|
78
|
-
hoveringNode.meta.locationIndex !== undefined &&
|
|
81
|
+
((_b = hoveringNode.meta) === null || _b === void 0 ? void 0 : _b.locationIndex) !== undefined &&
|
|
79
82
|
hoveringNode.meta.locationIndex !== 0) {
|
|
80
83
|
var location_1 = locations[hoveringNode.meta.locationIndex - 1];
|
|
81
84
|
hoveringNode.meta.location = location_1;
|
|
@@ -117,9 +120,10 @@ var TooltipMetaInfo = function (_a) {
|
|
|
117
120
|
? " +".concat(hoveringNode.meta.function.startLine)
|
|
118
121
|
: ''));
|
|
119
122
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
var file = getTextForFile(hoveringNode);
|
|
124
|
+
return (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "File" })), _jsx("td", __assign({ className: "w-3/4 break-all" }, { children: ((_d = (_c = hoveringNode.meta) === null || _c === void 0 ? void 0 : _c.function) === null || _d === void 0 ? void 0 : _d.filename) == null ||
|
|
125
|
+
((_e = hoveringNode.meta) === null || _e === void 0 ? void 0 : _e.function.filename) === '' ? (_jsx(NoData, {})) : (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: file }, { children: _jsx("button", __assign({ className: "cursor-pointer text-left whitespace-nowrap" }, { children: _jsx(ExpandOnHover, { value: file, displayValue: truncateStringReverse(file, 40) }) })) }))) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Address" })), _jsx("td", __assign({ className: "w-3/4 break-all" }, { children: ((_g = (_f = hoveringNode.meta) === null || _f === void 0 ? void 0 : _f.location) === null || _g === void 0 ? void 0 : _g.address) == null ||
|
|
126
|
+
((_h = hoveringNode.meta) === null || _h === void 0 ? void 0 : _h.location.address) === '0' ? (_jsx(NoData, {})) : (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hexifyAddress(hoveringNode.meta.location.address) }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: hexifyAddress(hoveringNode.meta.location.address) })) }))) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Binary" })), _jsx("td", __assign({ className: "w-3/4 break-all" }, { children: ((_j = hoveringNode.meta) === null || _j === void 0 ? void 0 : _j.mapping) == null || hoveringNode.meta.mapping.file === '' ? (_jsx(NoData, {})) : (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hoveringNode.meta.mapping.file }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: getLastItem(hoveringNode.meta.mapping.file) })) }))) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Build Id" })), _jsx("td", __assign({ className: "w-3/4 break-all" }, { children: ((_k = hoveringNode.meta) === null || _k === void 0 ? void 0 : _k.mapping) == null || ((_l = hoveringNode.meta) === null || _l === void 0 ? void 0 : _l.mapping.buildId) === '' ? (_jsx(NoData, {})) : (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hoveringNode.meta.mapping.buildId }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: truncateString(getLastItem(hoveringNode.meta.mapping.buildId), 28) })) }))) }))] })] }));
|
|
123
127
|
};
|
|
124
128
|
var timeoutHandle = null;
|
|
125
129
|
var GraphTooltipContent = function (_a) {
|
|
@@ -140,21 +144,20 @@ var GraphTooltipContent = function (_a) {
|
|
|
140
144
|
var diffValueText = diffSign + valueFormatter(diff, unit, 1);
|
|
141
145
|
var diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
|
|
142
146
|
var diffText = "".concat(diffValueText, " (").concat(diffPercentageText, ")");
|
|
143
|
-
var metaRows = hoveringNode.meta === undefined ? (_jsx(_Fragment, {})) : (_jsx(TooltipMetaInfo, { onCopy: onCopy,
|
|
144
|
-
// @ts-expect-error
|
|
145
|
-
hoveringNode: hoveringNode, strings: strings, mappings: mappings, locations: locations, functions: functions }));
|
|
146
147
|
var getTextForCumulative = function (hoveringNodeCumulative) {
|
|
147
148
|
return "".concat(valueFormatter(hoveringNodeCumulative, unit, 2), " (\n ").concat(((hoveringNodeCumulative * 100) / total).toFixed(2), "%)");
|
|
148
149
|
};
|
|
149
|
-
return (_jsx("div", __assign({ className: "flex ".concat(isFixed ? 'w-full
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
return (_jsx("div", __assign({ className: "text-sm flex ".concat(isFixed ? 'w-full' : '') }, { children: _jsx("div", __assign({ className: "m-auto w-full ".concat(isFixed ? 'w-full' : '') }, { children: _jsxs("div", __assign({ className: "border border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg min-h-52 w-[500px] flex justify-between flex-col" }, { children: [_jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "mx-2" }, { children: [_jsx("div", __assign({ className: "font-semibold break-all h-10 flex items-center" }, { children: hoveringNode.meta === undefined ? (_jsx("p", { children: "root" })) : (_jsx(_Fragment, { children: hoveringNode.meta.function !== undefined &&
|
|
151
|
+
hoveringNode.meta.function.name !== '' ? (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hoveringNode.meta.function.name }, { children: _jsx("button", __assign({ className: "cursor-pointer text-left" }, { children: hoveringNode.meta.function.name })) }))) : (_jsx(_Fragment, { children: hoveringNode.meta.location !== undefined &&
|
|
152
|
+
parseInt(hoveringNode.meta.location.address, 10) !== 0 ? (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hexifyAddress(hoveringNode.meta.location.address) }, { children: _jsx("button", __assign({ className: "cursor-pointer text-left" }, { children: hexifyAddress(hoveringNode.meta.location.address) })) }))) : (_jsx("p", { children: "unknown" })) })) })) })), _jsx("table", __assign({ className: "table-fixed pr-0 text-gray-700 dark:text-gray-300 my-2 w-full" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Cumulative" })), _jsx("td", __assign({ className: "w-3/4" }, { children: _jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: getTextForCumulative(hoveringNodeCumulative) }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: getTextForCumulative(hoveringNodeCumulative) })) })) }))] }), hoveringNode.diff !== undefined && diff !== 0 && (_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Diff" })), _jsx("td", __assign({ className: "w-3/4" }, { children: _jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: diffText }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: diffText })) })) }))] })), _jsx(TooltipMetaInfo, { onCopy: onCopy,
|
|
153
|
+
// @ts-expect-error
|
|
154
|
+
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.' }))] })) })) })));
|
|
152
155
|
};
|
|
153
156
|
var GraphTooltip = function (_a) {
|
|
154
157
|
var x = _a.x, y = _a.y, unit = _a.unit, total = _a.total, hoveringNode = _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;
|
|
155
158
|
var _d = useState(null), popperElement = _d[0], setPopperElement = _d[1];
|
|
156
159
|
var _e = usePopper(virtualContextElement ? virtualElement : contextElement, popperElement, {
|
|
157
|
-
placement: '
|
|
160
|
+
placement: 'bottom-start',
|
|
158
161
|
strategy: 'absolute',
|
|
159
162
|
modifiers: [
|
|
160
163
|
{
|
|
@@ -172,16 +175,30 @@ var GraphTooltip = function (_a) {
|
|
|
172
175
|
},
|
|
173
176
|
],
|
|
174
177
|
}), styles = _e.styles, attributes = _e.attributes, popperProps = __rest(_e, ["styles", "attributes"]);
|
|
175
|
-
var update = popperProps.update;
|
|
176
178
|
var isShiftDown = useKeyDown().isShiftDown;
|
|
177
179
|
useEffect(function () {
|
|
178
|
-
if (contextElement
|
|
179
|
-
|
|
180
|
+
if (contextElement === null)
|
|
181
|
+
return;
|
|
182
|
+
var onMouseMove = function (e) {
|
|
183
|
+
var _a;
|
|
184
|
+
if (isShiftDown) {
|
|
180
185
|
return;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
}
|
|
187
|
+
var tooltipX = x;
|
|
188
|
+
var tooltipY = y;
|
|
189
|
+
if (tooltipX == null || tooltipY == null) {
|
|
190
|
+
var rel = pointer(e);
|
|
191
|
+
tooltipX = rel[0];
|
|
192
|
+
tooltipY = rel[1];
|
|
193
|
+
}
|
|
194
|
+
virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, tooltipX, tooltipY);
|
|
195
|
+
void ((_a = popperProps.update) === null || _a === void 0 ? void 0 : _a.call(popperProps));
|
|
196
|
+
};
|
|
197
|
+
contextElement.addEventListener('mousemove', onMouseMove);
|
|
198
|
+
return function () {
|
|
199
|
+
contextElement.removeEventListener('mousemove', onMouseMove);
|
|
200
|
+
};
|
|
201
|
+
}, [contextElement, popperProps, isShiftDown, x, y]);
|
|
185
202
|
if (hoveringNode === undefined || hoveringNode == null)
|
|
186
203
|
return _jsx(_Fragment, {});
|
|
187
204
|
return isFixed ? (_jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, isFixed: isFixed })) : (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { children: _jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, isFixed: isFixed, strings: strings, mappings: mappings, locations: locations, functions: functions }) })));
|
|
@@ -99,9 +99,9 @@ export var IcicleNode = React.memo(function IcicleNode(_a) {
|
|
|
99
99
|
};
|
|
100
100
|
return (_jsxs(_Fragment, { children: [_jsxs("g", __assign({ transform: "translate(".concat(x + 1, ", ").concat(y + 1, ")"), style: styles, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: function () {
|
|
101
101
|
setCurPath(nextPath);
|
|
102
|
-
} }, { children: [_jsx("rect", { x: 0, y: 0, width: width
|
|
102
|
+
} }, { children: [_jsx("rect", { x: 0, y: 0, width: width, height: height, style: {
|
|
103
103
|
fill: colorResult,
|
|
104
|
-
}, className: cx({
|
|
104
|
+
}, className: cx('stroke-white dark:stroke-gray-700', {
|
|
105
105
|
'opacity-50': isHighlightEnabled && !isHighlighted,
|
|
106
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, setHoveringNode: setHoveringNode, path: nextPath, curPath: nextCurPath, setCurPath: setCurPath, searchString: searchString, compareMode: compareMode }))] }));
|
|
107
107
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
2
|
import { Flamegraph } from '@parca/client';
|
|
3
3
|
import { type NavigateFunction } from '@parca/functions';
|
|
4
4
|
interface IcicleGraphProps {
|
|
@@ -10,5 +10,5 @@ interface IcicleGraphProps {
|
|
|
10
10
|
navigateTo?: NavigateFunction;
|
|
11
11
|
isTrimmed?: boolean;
|
|
12
12
|
}
|
|
13
|
-
export declare const IcicleGraph:
|
|
13
|
+
export declare const IcicleGraph: import("react").NamedExoticComponent<IcicleGraphProps>;
|
|
14
14
|
export default IcicleGraph;
|
|
@@ -25,8 +25,6 @@ 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 cx from 'classnames';
|
|
27
27
|
import { scaleLinear } from 'd3-scale';
|
|
28
|
-
import { pointer } from 'd3-selection';
|
|
29
|
-
import { throttle } from 'lodash';
|
|
30
28
|
import { Button, useURLState } from '@parca/components';
|
|
31
29
|
import { selectQueryParam } from '@parca/functions';
|
|
32
30
|
import useUserPreference, { USER_PREFERENCES } from '@parca/functions/useUserPreference';
|
|
@@ -38,8 +36,7 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
|
38
36
|
var _b;
|
|
39
37
|
var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo, _c = _a.isTrimmed, isTrimmed = _c === void 0 ? false : _c;
|
|
40
38
|
var _d = useState(), hoveringNode = _d[0], setHoveringNode = _d[1];
|
|
41
|
-
var _e = useState(
|
|
42
|
-
var _f = useState(0), height = _f[0], setHeight = _f[1];
|
|
39
|
+
var _e = useState(0), height = _e[0], setHeight = _e[1];
|
|
43
40
|
var svg = useRef(null);
|
|
44
41
|
var ref = useRef(null);
|
|
45
42
|
var rawDashboardItems = useURLState({
|
|
@@ -65,14 +62,8 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
|
65
62
|
if (coloredGraph.root === undefined || width === undefined) {
|
|
66
63
|
return _jsx(_Fragment, {});
|
|
67
64
|
}
|
|
68
|
-
var throttledSetPos = throttle(setPos, 20);
|
|
69
|
-
var onMouseMove = function (e) {
|
|
70
|
-
// X/Y coordinate array relative to svg
|
|
71
|
-
var rel = pointer(e);
|
|
72
|
-
throttledSetPos([rel[0], rel[1]]);
|
|
73
|
-
};
|
|
74
65
|
var isColorStackLegendVisible = colorProfileName !== 'default';
|
|
75
|
-
return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total,
|
|
66
|
+
return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total, hoveringNode: hoveringNode, contextElement: svg.current, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function }), _jsx("div", __assign({ className: cx('flex justify-start absolute', {
|
|
76
67
|
'top-[-48px]': dashboardItems.length <= 1 && !isTrimmed && !isColorStackLegendVisible,
|
|
77
68
|
'top-[-69px]': dashboardItems.length <= 1 && !isTrimmed && isColorStackLegendVisible,
|
|
78
69
|
'top-[-54px]': dashboardItems.length <= 1 && isTrimmed && isColorStackLegendVisible,
|
|
@@ -81,6 +72,6 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
|
81
72
|
'top-[-54px] left-[25px] ': dashboardItems.length > 1 && isTrimmed && !isColorStackLegendVisible,
|
|
82
73
|
'top-[-70px] left-[25px]': dashboardItems.length > 1 && !isTrimmed && isColorStackLegendVisible,
|
|
83
74
|
'top-[-46px] left-[25px]': dashboardItems.length > 1 && !isTrimmed && !isColorStackLegendVisible,
|
|
84
|
-
}) }, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset View" })) })), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height,
|
|
75
|
+
}) }, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset View" })) })), _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, setHoveringNode: setHoveringNode, 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 }) })) })) }))] })));
|
|
85
76
|
});
|
|
86
77
|
export default IcicleGraph;
|
|
@@ -37,7 +37,7 @@ import { Icon } from '@iconify/react';
|
|
|
37
37
|
import cx from 'classnames';
|
|
38
38
|
import { scaleLinear } from 'd3';
|
|
39
39
|
import { DragDropContext, Draggable, Droppable, } from 'react-beautiful-dnd';
|
|
40
|
-
import { Button, Card, KeyDownProvider, useParcaContext, useURLState } from '@parca/components';
|
|
40
|
+
import { Button, Card, ConditionalWrapper, KeyDownProvider, useParcaContext, useURLState, } from '@parca/components';
|
|
41
41
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
42
42
|
import { getNewSpanColor } from '@parca/functions';
|
|
43
43
|
import { CloseIcon } from '@parca/icons';
|
|
@@ -100,7 +100,10 @@ export var ProfileView = function (_a) {
|
|
|
100
100
|
var type = _a.type, isHalfScreen = _a.isHalfScreen;
|
|
101
101
|
switch (type) {
|
|
102
102
|
case 'icicle': {
|
|
103
|
-
return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(
|
|
103
|
+
return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(ConditionalWrapper, __assign({ condition: (perf === null || perf === void 0 ? void 0 : perf.onRender) != null, WrapperComponent: Profiler, wrapperProps: {
|
|
104
|
+
id: 'icicleGraph',
|
|
105
|
+
onRender: perf === null || perf === void 0 ? void 0 : perf.onRender,
|
|
106
|
+
} }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading }) }))) : (_jsx(_Fragment, { children: " " }));
|
|
104
107
|
}
|
|
105
108
|
case 'callgraph': {
|
|
106
109
|
return (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) != null && (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) !== undefined ? (_jsx(Callgraph, { graph: callgraphData.data, sampleUnit: sampleUnit, width: isHalfScreen ? (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) / 2 : dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, colorRange: colorRange })) : (_jsx(_Fragment, {}));
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-\[-45px\]{top:-45px}.top-\[-48px\]{top:-48px}.top-\[-69px\]{top:-69px}.top-\[-54px\]{top:-54px}.top-\[-70px\]{top:-70px}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-3{margin-right:.75rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-36{height:9rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-auto{width:auto}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-full{width:100%}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
|
|
1
|
+
/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-\[-45px\]{top:-45px}.top-\[-48px\]{top:-48px}.top-\[-69px\]{top:-69px}.top-\[-54px\]{top:-54px}.top-\[-70px\]{top:-70px}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mt-1{margin-top:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-6{margin-right:1.5rem}.mr-3{margin-right:.75rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.min-h-52{min-height:13rem}.w-auto{width:auto}.w-full{width:100%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-\[500px\]{max-width:500px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-white{stroke:#fff}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pr-0{padding-right:0}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
|
package/dist/utils.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ import { QueryRequest, QueryServiceClient } from '@parca/client';
|
|
|
3
3
|
export declare const hexifyAddress: (address?: string) => string;
|
|
4
4
|
export declare const downloadPprof: (request: QueryRequest, queryClient: QueryServiceClient, metadata: RpcMetadata) => Promise<Blob>;
|
|
5
5
|
export declare const truncateString: (str: string, num: number) => string;
|
|
6
|
+
export declare const truncateStringReverse: (str: string, num: number) => string;
|
package/dist/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.122",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@parca/client": "^0.16.63",
|
|
7
|
-
"@parca/components": "^0.16.
|
|
7
|
+
"@parca/components": "^0.16.102",
|
|
8
8
|
"@parca/dynamicsize": "^0.16.53",
|
|
9
9
|
"@parca/functions": "^0.16.63",
|
|
10
10
|
"@parca/parser": "^0.16.54",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"access": "public",
|
|
46
46
|
"registry": "https://registry.npmjs.org/"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "c2165c6991e55c1afd7d11e9c797a3de58578959"
|
|
49
49
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
interface Props {
|
|
15
|
+
value: string | number | undefined;
|
|
16
|
+
displayValue?: string | number | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ExpandOnHover = ({value, displayValue}: Props): JSX.Element => {
|
|
20
|
+
return (
|
|
21
|
+
<div className="relative group w-full">
|
|
22
|
+
<div className="text-ellipsis w-full overflow-hidden whitespace-nowrap">
|
|
23
|
+
{displayValue ?? value}
|
|
24
|
+
</div>
|
|
25
|
+
<div className="group-hover:flex hidden absolute -inset-2 max-w-[500px] whitespace-normal h-fit bg-gray-50 dark:bg-gray-900 shadow-[0_0_10px_2px_rgba(0,0,0,0.3)] rounded p-2 break-all">
|
|
26
|
+
{value}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {useEffect, useState} from 'react';
|
|
15
15
|
|
|
16
|
+
import {pointer} from 'd3-selection';
|
|
16
17
|
import {CopyToClipboard} from 'react-copy-to-clipboard';
|
|
17
18
|
import {usePopper} from 'react-popper';
|
|
18
19
|
|
|
@@ -25,11 +26,16 @@ import {
|
|
|
25
26
|
import {useKeyDown} from '@parca/components';
|
|
26
27
|
import {getLastItem, valueFormatter} from '@parca/functions';
|
|
27
28
|
|
|
28
|
-
import {hexifyAddress, truncateString} from '../';
|
|
29
|
+
import {hexifyAddress, truncateString, truncateStringReverse} from '../';
|
|
30
|
+
import {ExpandOnHover} from './ExpandOnHoverValue';
|
|
31
|
+
|
|
32
|
+
const NoData = (): JSX.Element => {
|
|
33
|
+
return <span className="rounded bg-gray-200 dark:bg-gray-800 px-2">Not available</span>;
|
|
34
|
+
};
|
|
29
35
|
|
|
30
36
|
interface GraphTooltipProps {
|
|
31
|
-
x
|
|
32
|
-
y
|
|
37
|
+
x?: number;
|
|
38
|
+
y?: number;
|
|
33
39
|
unit: string;
|
|
34
40
|
total: number;
|
|
35
41
|
hoveringNode: HoveringNode;
|
|
@@ -84,12 +90,10 @@ const TooltipMetaInfo = ({
|
|
|
84
90
|
locations?: Location[];
|
|
85
91
|
functions?: ParcaFunction[];
|
|
86
92
|
}): JSX.Element => {
|
|
87
|
-
if (hoveringNode.meta === undefined) return <></>;
|
|
88
|
-
|
|
89
93
|
// populate meta from the flamegraph metadata tables
|
|
90
94
|
if (
|
|
91
95
|
locations !== undefined &&
|
|
92
|
-
hoveringNode.meta
|
|
96
|
+
hoveringNode.meta?.locationIndex !== undefined &&
|
|
93
97
|
hoveringNode.meta.locationIndex !== 0
|
|
94
98
|
) {
|
|
95
99
|
const location = locations[hoveringNode.meta.locationIndex - 1];
|
|
@@ -142,60 +146,73 @@ const TooltipMetaInfo = ({
|
|
|
142
146
|
}`
|
|
143
147
|
}`;
|
|
144
148
|
};
|
|
149
|
+
const file = getTextForFile(hoveringNode);
|
|
145
150
|
|
|
146
151
|
return (
|
|
147
152
|
<>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
153
|
+
<tr>
|
|
154
|
+
<td className="w-1/4">File</td>
|
|
155
|
+
<td className="w-3/4 break-all">
|
|
156
|
+
{hoveringNode.meta?.function?.filename == null ||
|
|
157
|
+
hoveringNode.meta?.function.filename === '' ? (
|
|
158
|
+
<NoData />
|
|
159
|
+
) : (
|
|
160
|
+
<CopyToClipboard onCopy={onCopy} text={file}>
|
|
161
|
+
<button className="cursor-pointer text-left whitespace-nowrap">
|
|
162
|
+
<ExpandOnHover value={file} displayValue={truncateStringReverse(file, 40)} />
|
|
163
|
+
</button>
|
|
164
|
+
</CopyToClipboard>
|
|
165
|
+
)}
|
|
166
|
+
</td>
|
|
167
|
+
</tr>
|
|
168
|
+
|
|
169
|
+
<tr>
|
|
170
|
+
<td className="w-1/4">Address</td>
|
|
171
|
+
<td className="w-3/4 break-all">
|
|
172
|
+
{hoveringNode.meta?.location?.address == null ||
|
|
173
|
+
hoveringNode.meta?.location.address === '0' ? (
|
|
174
|
+
<NoData />
|
|
175
|
+
) : (
|
|
176
|
+
<CopyToClipboard
|
|
177
|
+
onCopy={onCopy}
|
|
178
|
+
text={hexifyAddress(hoveringNode.meta.location.address)}
|
|
179
|
+
>
|
|
180
|
+
<button className="cursor-pointer">
|
|
181
|
+
{hexifyAddress(hoveringNode.meta.location.address)}
|
|
182
|
+
</button>
|
|
183
|
+
</CopyToClipboard>
|
|
184
|
+
)}
|
|
185
|
+
</td>
|
|
186
|
+
</tr>
|
|
187
|
+
<tr>
|
|
188
|
+
<td className="w-1/4">Binary</td>
|
|
189
|
+
<td className="w-3/4 break-all">
|
|
190
|
+
{hoveringNode.meta?.mapping == null || hoveringNode.meta.mapping.file === '' ? (
|
|
191
|
+
<NoData />
|
|
192
|
+
) : (
|
|
179
193
|
<CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.file}>
|
|
180
194
|
<button className="cursor-pointer">
|
|
181
195
|
{getLastItem(hoveringNode.meta.mapping.file)}
|
|
182
196
|
</button>
|
|
183
197
|
</CopyToClipboard>
|
|
184
|
-
|
|
185
|
-
</
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
)}
|
|
199
|
+
</td>
|
|
200
|
+
</tr>
|
|
201
|
+
|
|
202
|
+
<tr>
|
|
203
|
+
<td className="w-1/4">Build Id</td>
|
|
204
|
+
<td className="w-3/4 break-all">
|
|
205
|
+
{hoveringNode.meta?.mapping == null || hoveringNode.meta?.mapping.buildId === '' ? (
|
|
206
|
+
<NoData />
|
|
207
|
+
) : (
|
|
191
208
|
<CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.buildId}>
|
|
192
209
|
<button className="cursor-pointer">
|
|
193
|
-
{truncateString(getLastItem(hoveringNode.meta.mapping.buildId) as string,
|
|
210
|
+
{truncateString(getLastItem(hoveringNode.meta.mapping.buildId) as string, 28)}
|
|
194
211
|
</button>
|
|
195
212
|
</CopyToClipboard>
|
|
196
|
-
|
|
197
|
-
</
|
|
198
|
-
|
|
213
|
+
)}
|
|
214
|
+
</td>
|
|
215
|
+
</tr>
|
|
199
216
|
</>
|
|
200
217
|
);
|
|
201
218
|
};
|
|
@@ -246,20 +263,6 @@ const GraphTooltipContent = ({
|
|
|
246
263
|
const diffValueText = diffSign + valueFormatter(diff, unit, 1);
|
|
247
264
|
const diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
|
|
248
265
|
const diffText = `${diffValueText} (${diffPercentageText})`;
|
|
249
|
-
const metaRows =
|
|
250
|
-
hoveringNode.meta === undefined ? (
|
|
251
|
-
<></>
|
|
252
|
-
) : (
|
|
253
|
-
<TooltipMetaInfo
|
|
254
|
-
onCopy={onCopy}
|
|
255
|
-
// @ts-expect-error
|
|
256
|
-
hoveringNode={hoveringNode}
|
|
257
|
-
strings={strings}
|
|
258
|
-
mappings={mappings}
|
|
259
|
-
locations={locations}
|
|
260
|
-
functions={functions}
|
|
261
|
-
/>
|
|
262
|
-
);
|
|
263
266
|
|
|
264
267
|
const getTextForCumulative = (hoveringNodeCumulative: number): string => {
|
|
265
268
|
return `${valueFormatter(hoveringNodeCumulative, unit, 2)} (
|
|
@@ -267,15 +270,12 @@ const GraphTooltipContent = ({
|
|
|
267
270
|
};
|
|
268
271
|
|
|
269
272
|
return (
|
|
270
|
-
<div className={`flex ${isFixed ? 'w-full
|
|
271
|
-
<div className={`m-auto w-full ${isFixed ? 'w-full
|
|
272
|
-
<div
|
|
273
|
-
className="border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90"
|
|
274
|
-
style={{borderWidth: 1}}
|
|
275
|
-
>
|
|
273
|
+
<div className={`text-sm flex ${isFixed ? 'w-full' : ''}`}>
|
|
274
|
+
<div className={`m-auto w-full ${isFixed ? 'w-full' : ''}`}>
|
|
275
|
+
<div className="border border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg min-h-52 w-[500px] flex justify-between flex-col">
|
|
276
276
|
<div className="flex flex-row">
|
|
277
|
-
<div className="
|
|
278
|
-
<
|
|
277
|
+
<div className="mx-2">
|
|
278
|
+
<div className="font-semibold break-all h-10 flex items-center">
|
|
279
279
|
{hoveringNode.meta === undefined ? (
|
|
280
280
|
<p>root</p>
|
|
281
281
|
) : (
|
|
@@ -306,44 +306,49 @@ const GraphTooltipContent = ({
|
|
|
306
306
|
)}
|
|
307
307
|
</>
|
|
308
308
|
)}
|
|
309
|
-
</
|
|
310
|
-
<
|
|
311
|
-
<
|
|
312
|
-
<
|
|
309
|
+
</div>
|
|
310
|
+
<table className="table-fixed pr-0 text-gray-700 dark:text-gray-300 my-2 w-full">
|
|
311
|
+
<tbody>
|
|
312
|
+
<tr>
|
|
313
|
+
<td className="w-1/4">Cumulative</td>
|
|
314
|
+
|
|
315
|
+
<td className="w-3/4">
|
|
316
|
+
<CopyToClipboard
|
|
317
|
+
onCopy={onCopy}
|
|
318
|
+
text={getTextForCumulative(hoveringNodeCumulative)}
|
|
319
|
+
>
|
|
320
|
+
<button className="cursor-pointer">
|
|
321
|
+
{getTextForCumulative(hoveringNodeCumulative)}
|
|
322
|
+
</button>
|
|
323
|
+
</CopyToClipboard>
|
|
324
|
+
</td>
|
|
325
|
+
</tr>
|
|
326
|
+
{hoveringNode.diff !== undefined && diff !== 0 && (
|
|
313
327
|
<tr>
|
|
314
|
-
<td className="w-1/
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
onCopy={onCopy}
|
|
319
|
-
text={getTextForCumulative(hoveringNodeCumulative)}
|
|
320
|
-
>
|
|
321
|
-
<button className="cursor-pointer">
|
|
322
|
-
{getTextForCumulative(hoveringNodeCumulative)}
|
|
323
|
-
</button>
|
|
328
|
+
<td className="w-1/4">Diff</td>
|
|
329
|
+
<td className="w-3/4">
|
|
330
|
+
<CopyToClipboard onCopy={onCopy} text={diffText}>
|
|
331
|
+
<button className="cursor-pointer">{diffText}</button>
|
|
324
332
|
</CopyToClipboard>
|
|
325
333
|
</td>
|
|
326
334
|
</tr>
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
</table>
|
|
340
|
-
</span>
|
|
341
|
-
|
|
342
|
-
<span className="block text-gray-500 text-xs mt-2">
|
|
343
|
-
{isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.'}
|
|
344
|
-
</span>
|
|
335
|
+
)}
|
|
336
|
+
<TooltipMetaInfo
|
|
337
|
+
onCopy={onCopy}
|
|
338
|
+
// @ts-expect-error
|
|
339
|
+
hoveringNode={hoveringNode}
|
|
340
|
+
strings={strings}
|
|
341
|
+
mappings={mappings}
|
|
342
|
+
locations={locations}
|
|
343
|
+
functions={functions}
|
|
344
|
+
/>
|
|
345
|
+
</tbody>
|
|
346
|
+
</table>
|
|
345
347
|
</div>
|
|
346
348
|
</div>
|
|
349
|
+
<span className="block text-gray-500 text-xs mx-2">
|
|
350
|
+
{isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.'}
|
|
351
|
+
</span>
|
|
347
352
|
</div>
|
|
348
353
|
</div>
|
|
349
354
|
</div>
|
|
@@ -370,7 +375,7 @@ const GraphTooltip = ({
|
|
|
370
375
|
virtualContextElement ? virtualElement : contextElement,
|
|
371
376
|
popperElement,
|
|
372
377
|
{
|
|
373
|
-
placement: '
|
|
378
|
+
placement: 'bottom-start',
|
|
374
379
|
strategy: 'absolute',
|
|
375
380
|
modifiers: [
|
|
376
381
|
{
|
|
@@ -390,17 +395,36 @@ const GraphTooltip = ({
|
|
|
390
395
|
}
|
|
391
396
|
);
|
|
392
397
|
|
|
393
|
-
const update = popperProps.update;
|
|
394
398
|
const {isShiftDown} = useKeyDown();
|
|
395
399
|
|
|
396
400
|
useEffect(() => {
|
|
397
|
-
if (contextElement
|
|
398
|
-
|
|
401
|
+
if (contextElement === null) return;
|
|
402
|
+
const onMouseMove: EventListenerOrEventListenerObject = (e: Event) => {
|
|
403
|
+
if (isShiftDown) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
399
406
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
407
|
+
let tooltipX = x;
|
|
408
|
+
let tooltipY = y;
|
|
409
|
+
if (tooltipX == null || tooltipY == null) {
|
|
410
|
+
const rel = pointer(e);
|
|
411
|
+
tooltipX = rel[0];
|
|
412
|
+
tooltipY = rel[1];
|
|
413
|
+
}
|
|
414
|
+
virtualElement.getBoundingClientRect = generateGetBoundingClientRect(
|
|
415
|
+
contextElement,
|
|
416
|
+
tooltipX,
|
|
417
|
+
tooltipY
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
void popperProps.update?.();
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
contextElement.addEventListener('mousemove', onMouseMove);
|
|
424
|
+
return () => {
|
|
425
|
+
contextElement.removeEventListener('mousemove', onMouseMove);
|
|
426
|
+
};
|
|
427
|
+
}, [contextElement, popperProps, isShiftDown, x, y]);
|
|
404
428
|
|
|
405
429
|
if (hoveringNode === undefined || hoveringNode == null) return <></>;
|
|
406
430
|
|
|
@@ -228,12 +228,12 @@ export const IcicleNode = React.memo(function IcicleNode({
|
|
|
228
228
|
<rect
|
|
229
229
|
x={0}
|
|
230
230
|
y={0}
|
|
231
|
-
width={width
|
|
232
|
-
height={height
|
|
231
|
+
width={width}
|
|
232
|
+
height={height}
|
|
233
233
|
style={{
|
|
234
234
|
fill: colorResult,
|
|
235
235
|
}}
|
|
236
|
-
className={cx({
|
|
236
|
+
className={cx('stroke-white dark:stroke-gray-700', {
|
|
237
237
|
'opacity-50': isHighlightEnabled && !isHighlighted,
|
|
238
238
|
})}
|
|
239
239
|
/>
|
|
@@ -11,12 +11,10 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import {memo, useEffect, useMemo, useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import {scaleLinear} from 'd3-scale';
|
|
18
|
-
import {pointer} from 'd3-selection';
|
|
19
|
-
import {throttle} from 'lodash';
|
|
20
18
|
|
|
21
19
|
import {Flamegraph, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
|
|
22
20
|
import {Button, useURLState} from '@parca/components';
|
|
@@ -50,7 +48,6 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
50
48
|
const [hoveringNode, setHoveringNode] = useState<
|
|
51
49
|
FlamegraphNode | FlamegraphRootNode | undefined
|
|
52
50
|
>();
|
|
53
|
-
const [pos, setPos] = useState([0, 0]);
|
|
54
51
|
const [height, setHeight] = useState(0);
|
|
55
52
|
const svg = useRef(null);
|
|
56
53
|
const ref = useRef<SVGGElement>(null);
|
|
@@ -86,13 +83,6 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
86
83
|
return <></>;
|
|
87
84
|
}
|
|
88
85
|
|
|
89
|
-
const throttledSetPos = throttle(setPos, 20);
|
|
90
|
-
const onMouseMove = (e: React.MouseEvent<SVGSVGElement | HTMLDivElement>): void => {
|
|
91
|
-
// X/Y coordinate array relative to svg
|
|
92
|
-
const rel = pointer(e);
|
|
93
|
-
|
|
94
|
-
throttledSetPos([rel[0], rel[1]]);
|
|
95
|
-
};
|
|
96
86
|
const isColorStackLegendVisible = colorProfileName !== 'default';
|
|
97
87
|
|
|
98
88
|
return (
|
|
@@ -101,8 +91,6 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
101
91
|
<GraphTooltip
|
|
102
92
|
unit={sampleUnit}
|
|
103
93
|
total={total}
|
|
104
|
-
x={pos[0]}
|
|
105
|
-
y={pos[1]}
|
|
106
94
|
hoveringNode={hoveringNode as HoveringNode}
|
|
107
95
|
contextElement={svg.current}
|
|
108
96
|
strings={coloredGraph.stringTable}
|
|
@@ -140,7 +128,6 @@ export const IcicleGraph = memo(function IcicleGraph({
|
|
|
140
128
|
className="font-robotoMono"
|
|
141
129
|
width={width}
|
|
142
130
|
height={height}
|
|
143
|
-
onMouseMove={onMouseMove}
|
|
144
131
|
preserveAspectRatio="xMinYMid"
|
|
145
132
|
ref={svg}
|
|
146
133
|
>
|
|
@@ -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 {Profiler, useEffect, useMemo, useState} from 'react';
|
|
14
|
+
import {Profiler, ProfilerProps, useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {Icon} from '@iconify/react';
|
|
17
17
|
import cx from 'classnames';
|
|
@@ -25,7 +25,14 @@ import {
|
|
|
25
25
|
} from 'react-beautiful-dnd';
|
|
26
26
|
|
|
27
27
|
import {Callgraph as CallgraphType, Flamegraph, QueryServiceClient, Top} from '@parca/client';
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
Button,
|
|
30
|
+
Card,
|
|
31
|
+
ConditionalWrapper,
|
|
32
|
+
KeyDownProvider,
|
|
33
|
+
useParcaContext,
|
|
34
|
+
useURLState,
|
|
35
|
+
} from '@parca/components';
|
|
29
36
|
import {useContainerDimensions} from '@parca/dynamicsize';
|
|
30
37
|
import {getNewSpanColor} from '@parca/functions';
|
|
31
38
|
import {CloseIcon} from '@parca/icons';
|
|
@@ -154,7 +161,14 @@ export const ProfileView = ({
|
|
|
154
161
|
switch (type) {
|
|
155
162
|
case 'icicle': {
|
|
156
163
|
return flamegraphData?.data != null ? (
|
|
157
|
-
<
|
|
164
|
+
<ConditionalWrapper<ProfilerProps>
|
|
165
|
+
condition={perf?.onRender != null}
|
|
166
|
+
WrapperComponent={Profiler}
|
|
167
|
+
wrapperProps={{
|
|
168
|
+
id: 'icicleGraph',
|
|
169
|
+
onRender: perf?.onRender as React.ProfilerOnRenderCallback,
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
158
172
|
<ProfileIcicleGraph
|
|
159
173
|
curPath={curPath}
|
|
160
174
|
setNewCurPath={setNewCurPath}
|
|
@@ -164,7 +178,7 @@ export const ProfileView = ({
|
|
|
164
178
|
navigateTo={navigateTo}
|
|
165
179
|
loading={flamegraphData.loading}
|
|
166
180
|
/>
|
|
167
|
-
</
|
|
181
|
+
</ConditionalWrapper>
|
|
168
182
|
) : (
|
|
169
183
|
<> </>
|
|
170
184
|
);
|
package/src/utils.ts
CHANGED
|
@@ -51,3 +51,11 @@ export const truncateString = (str: string, num: number): string => {
|
|
|
51
51
|
|
|
52
52
|
return str.slice(0, num) + '...';
|
|
53
53
|
};
|
|
54
|
+
|
|
55
|
+
export const truncateStringReverse = (str: string, num: number): string => {
|
|
56
|
+
if (str.length <= num) {
|
|
57
|
+
return str;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return '...' + str.slice(str.length - num);
|
|
61
|
+
};
|
package/tailwind.config.js
CHANGED
|
@@ -2,7 +2,17 @@ module.exports = {
|
|
|
2
2
|
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
|
|
3
3
|
darkMode: ['class', '[class~="theme-dark"]'],
|
|
4
4
|
theme: {
|
|
5
|
-
extend: {
|
|
5
|
+
extend: {
|
|
6
|
+
minHeight: theme => ({
|
|
7
|
+
...theme('spacing'),
|
|
8
|
+
}),
|
|
9
|
+
maxWidth: theme => ({
|
|
10
|
+
...theme('spacing'),
|
|
11
|
+
}),
|
|
12
|
+
minWidth: theme => ({
|
|
13
|
+
...theme('spacing'),
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
6
16
|
},
|
|
7
17
|
plugins: [],
|
|
8
18
|
};
|