@parca/profile 0.16.122 → 0.16.124
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/MetricsGraph/MetricsTooltip/index.js +1 -1
- package/dist/MetricsGraph/index.d.ts +1 -0
- package/dist/MetricsGraph/index.js +10 -8
- package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -1
- package/dist/ProfileIcicleGraph/IcicleGraph/index.js +4 -22
- package/dist/ProfileIcicleGraph/index.d.ts +2 -1
- package/dist/ProfileIcicleGraph/index.js +10 -3
- package/dist/ProfileSelector/index.js +13 -3
- package/dist/ProfileSource.d.ts +6 -8
- package/dist/ProfileSource.js +26 -18
- package/dist/ProfileView/VisualizationPanel.d.ts +18 -0
- package/dist/ProfileView/VisualizationPanel.js +38 -0
- package/dist/ProfileView/index.js +6 -10
- package/dist/TopTable/index.d.ts +4 -1
- package/dist/TopTable/index.js +12 -7
- package/dist/styles.css +1 -1
- package/package.json +6 -6
- package/src/MetricsGraph/MetricsTooltip/index.tsx +7 -1
- package/src/MetricsGraph/index.tsx +11 -8
- package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +0 -41
- package/src/ProfileIcicleGraph/index.tsx +23 -2
- package/src/ProfileSelector/index.tsx +14 -5
- package/src/ProfileSource.tsx +34 -51
- package/src/ProfileView/VisualizationPanel.tsx +79 -0
- package/src/ProfileView/index.tsx +16 -37
- package/src/TopTable/index.tsx +29 -20
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.124](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.123...@parca/profile@0.16.124) (2023-02-22)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.16.123](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.122...@parca/profile@0.16.123) (2023-02-22)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.122](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.121...@parca/profile@0.16.122) (2023-02-22)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -98,7 +98,7 @@ var MetricsTooltip = function (_a) {
|
|
|
98
98
|
}, [x, y, contextElement, update]);
|
|
99
99
|
var nameLabel = highlighted === null || highlighted === void 0 ? void 0 : highlighted.labels.find(function (e) { return e.name === '__name__'; });
|
|
100
100
|
var highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
|
|
101
|
-
return (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { className: "z-10" }, { children: _jsx("div", __assign({ className: "flex max-w-md" }, { children: _jsx("div", __assign({ className: "m-auto" }, { children: _jsx("div", __assign({ className: "border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90", style: { borderWidth: 1 } }, { children: _jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "ml-2 mr-6" }, { children: [_jsx("span", __assign({ className: "font-semibold" }, { children: highlightedNameLabel.value })), _jsx("span", __assign({ className: "block text-gray-700 dark:text-gray-300 my-2" }, { children: _jsx("table", __assign({ className: "table-auto" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Value" })), _jsx("td", __assign({ className: "w-3/4" }, { children: valueFormatter(highlighted.
|
|
101
|
+
return (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { className: "z-10" }, { children: _jsx("div", __assign({ className: "flex max-w-md" }, { children: _jsx("div", __assign({ className: "m-auto" }, { children: _jsx("div", __assign({ className: "border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90", style: { borderWidth: 1 } }, { children: _jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "ml-2 mr-6" }, { children: [_jsx("span", __assign({ className: "font-semibold" }, { children: highlightedNameLabel.value })), _jsx("span", __assign({ className: "block text-gray-700 dark:text-gray-300 my-2" }, { children: _jsx("table", __assign({ className: "table-auto" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Value" })), _jsx("td", __assign({ className: "w-3/4" }, { children: valueFormatter(highlighted.valuePerSecond, sampleUnit, 5) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Total" })), _jsx("td", __assign({ className: "w-3/4" }, { children: valueFormatter(highlighted.value, sampleUnit, 2) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "At" })), _jsx("td", __assign({ className: "w-3/4" }, { children: formatDate(highlighted.timestamp, timeFormat) }))] })] }) })) })), _jsx("span", __assign({ className: "block text-gray-500 my-2" }, { children: highlighted.labels
|
|
102
102
|
.filter(function (label) { return label.name !== '__name__'; })
|
|
103
103
|
.map(function (label) {
|
|
104
104
|
return (_jsx("button", __assign({ type: "button", className: "inline-block rounded-lg text-gray-700 bg-gray-200 dark:bg-gray-700 dark:text-gray-400 px-2 py-1 text-xs font-bold mr-3", onClick: function () { return onLabelClick(label.name, label.value); } }, { children: _jsx(TextWithTooltip, { text: "".concat(label.name, "=\"").concat(label.value, "\""), maxTextLength: 37, id: "tooltip-".concat(label.name, "-").concat(label.value) }) }), label.name));
|
|
@@ -68,9 +68,9 @@ export var RawMetricsGraph = function (_a) {
|
|
|
68
68
|
agg.push({
|
|
69
69
|
metric: s.labelset.labels,
|
|
70
70
|
values: s.samples.reduce(function (agg, d) {
|
|
71
|
-
if (d.timestamp !== undefined && d.
|
|
71
|
+
if (d.timestamp !== undefined && d.valuePerSecond !== undefined) {
|
|
72
72
|
var t = (+d.timestamp.seconds * 1e9 + d.timestamp.nanos) / 1e6; // https://github.com/microsoft/TypeScript/issues/5710#issuecomment-157886246
|
|
73
|
-
agg.push([t, parseFloat(d.value)]);
|
|
73
|
+
agg.push([t, d.valuePerSecond, parseFloat(d.value)]);
|
|
74
74
|
}
|
|
75
75
|
return agg;
|
|
76
76
|
}, []),
|
|
@@ -122,7 +122,8 @@ export var RawMetricsGraph = function (_a) {
|
|
|
122
122
|
seriesIndex: closestSeriesIndex,
|
|
123
123
|
labels: series[closestSeriesIndex].metric,
|
|
124
124
|
timestamp: point[0],
|
|
125
|
-
|
|
125
|
+
valuePerSecond: point[1],
|
|
126
|
+
value: point[2],
|
|
126
127
|
x: xScale(point[0]),
|
|
127
128
|
y: yScale(point[1]),
|
|
128
129
|
};
|
|
@@ -194,14 +195,14 @@ export var RawMetricsGraph = function (_a) {
|
|
|
194
195
|
var s = null;
|
|
195
196
|
var seriesIndex = -1;
|
|
196
197
|
outer: for (var i = 0; i < series.length; i++) {
|
|
197
|
-
var keys = profile.
|
|
198
|
+
var keys = profile.query.matchers.map(function (e) { return e.key; });
|
|
198
199
|
var _loop_1 = function (j) {
|
|
199
|
-
var
|
|
200
|
-
var label = series[i].metric.find(function (e) { return e.name ===
|
|
200
|
+
var matcherKey = keys[j];
|
|
201
|
+
var label = series[i].metric.find(function (e) { return e.name === matcherKey; });
|
|
201
202
|
if (label === undefined) {
|
|
202
203
|
return "continue-outer";
|
|
203
204
|
}
|
|
204
|
-
if (profile.
|
|
205
|
+
if (profile.query.matchers[j].value !== label.value) {
|
|
205
206
|
return "continue-outer";
|
|
206
207
|
}
|
|
207
208
|
};
|
|
@@ -228,7 +229,8 @@ export var RawMetricsGraph = function (_a) {
|
|
|
228
229
|
labels: [],
|
|
229
230
|
seriesIndex: seriesIndex,
|
|
230
231
|
timestamp: sample[0],
|
|
231
|
-
|
|
232
|
+
valuePerSecond: sample[1],
|
|
233
|
+
value: sample[2],
|
|
232
234
|
x: xScale(sample[0]),
|
|
233
235
|
y: yScale(sample[1]),
|
|
234
236
|
};
|
|
@@ -8,7 +8,6 @@ interface IcicleGraphProps {
|
|
|
8
8
|
curPath: string[];
|
|
9
9
|
setCurPath: (path: string[]) => void;
|
|
10
10
|
navigateTo?: NavigateFunction;
|
|
11
|
-
isTrimmed?: boolean;
|
|
12
11
|
}
|
|
13
12
|
export declare const IcicleGraph: import("react").NamedExoticComponent<IcicleGraphProps>;
|
|
14
13
|
export default IcicleGraph;
|
|
@@ -23,30 +23,22 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
23
23
|
// See the License for the specific language governing permissions and
|
|
24
24
|
// limitations under the License.
|
|
25
25
|
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
|
26
|
-
import cx from 'classnames';
|
|
27
26
|
import { scaleLinear } from 'd3-scale';
|
|
28
|
-
import { Button, useURLState } from '@parca/components';
|
|
29
27
|
import { selectQueryParam } from '@parca/functions';
|
|
30
|
-
import useUserPreference, { USER_PREFERENCES } from '@parca/functions/useUserPreference';
|
|
31
28
|
import GraphTooltip from '../../GraphTooltip';
|
|
32
29
|
import ColorStackLegend from './ColorStackLegend';
|
|
33
30
|
import { IcicleNode, RowHeight } from './IcicleGraphNodes';
|
|
34
31
|
import useColoredGraph from './useColoredGraph';
|
|
35
32
|
export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
36
33
|
var _b;
|
|
37
|
-
var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo
|
|
38
|
-
var
|
|
39
|
-
var
|
|
34
|
+
var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo;
|
|
35
|
+
var _c = useState(), hoveringNode = _c[0], setHoveringNode = _c[1];
|
|
36
|
+
var _d = useState(0), height = _d[0], setHeight = _d[1];
|
|
40
37
|
var svg = useRef(null);
|
|
41
38
|
var ref = useRef(null);
|
|
42
|
-
var rawDashboardItems = useURLState({
|
|
43
|
-
param: 'dashboard_items',
|
|
44
|
-
})[0];
|
|
45
|
-
var dashboardItems = rawDashboardItems;
|
|
46
39
|
var coloredGraph = useColoredGraph(graph);
|
|
47
40
|
var currentSearchString = (_b = selectQueryParam('search_string')) !== null && _b !== void 0 ? _b : '';
|
|
48
41
|
var compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
|
|
49
|
-
var colorProfileName = useUserPreference(USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key)[0];
|
|
50
42
|
useEffect(function () {
|
|
51
43
|
if (ref.current != null) {
|
|
52
44
|
setHeight(ref === null || ref === void 0 ? void 0 : ref.current.getBoundingClientRect().height);
|
|
@@ -62,16 +54,6 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
|
|
|
62
54
|
if (coloredGraph.root === undefined || width === undefined) {
|
|
63
55
|
return _jsx(_Fragment, {});
|
|
64
56
|
}
|
|
65
|
-
|
|
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', {
|
|
67
|
-
'top-[-48px]': dashboardItems.length <= 1 && !isTrimmed && !isColorStackLegendVisible,
|
|
68
|
-
'top-[-69px]': dashboardItems.length <= 1 && !isTrimmed && isColorStackLegendVisible,
|
|
69
|
-
'top-[-54px]': dashboardItems.length <= 1 && isTrimmed && isColorStackLegendVisible,
|
|
70
|
-
'top-[-54px] ': dashboardItems.length <= 1 && isTrimmed && !isColorStackLegendVisible,
|
|
71
|
-
'top-[-54px] left-[25px]': dashboardItems.length > 1 && isTrimmed && isColorStackLegendVisible,
|
|
72
|
-
'top-[-54px] left-[25px] ': dashboardItems.length > 1 && isTrimmed && !isColorStackLegendVisible,
|
|
73
|
-
'top-[-70px] left-[25px]': dashboardItems.length > 1 && !isTrimmed && isColorStackLegendVisible,
|
|
74
|
-
'top-[-46px] left-[25px]': dashboardItems.length > 1 && !isTrimmed && !isColorStackLegendVisible,
|
|
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 }) })) })) }))] })));
|
|
57
|
+
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("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 }) })) })) }))] })));
|
|
76
58
|
});
|
|
77
59
|
export default IcicleGraph;
|
|
@@ -10,6 +10,7 @@ interface ProfileIcicleGraphProps {
|
|
|
10
10
|
onContainerResize?: ResizeHandler;
|
|
11
11
|
navigateTo?: NavigateFunction;
|
|
12
12
|
loading: boolean;
|
|
13
|
+
setActionButtons?: (buttons: JSX.Element) => void;
|
|
13
14
|
}
|
|
14
|
-
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, onContainerResize, navigateTo, loading, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
15
|
+
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, onContainerResize, navigateTo, loading, setActionButtons, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
15
16
|
export default ProfileIcicleGraph;
|
|
@@ -23,13 +23,14 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
23
23
|
// See the License for the specific language governing permissions and
|
|
24
24
|
// limitations under the License.
|
|
25
25
|
import { useEffect, useMemo } from 'react';
|
|
26
|
+
import { Button } from '@parca/components';
|
|
26
27
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
27
28
|
import { selectQueryParam } from '@parca/functions';
|
|
28
29
|
import DiffLegend from '../components/DiffLegend';
|
|
29
|
-
import IcicleGraph from './IcicleGraph';
|
|
30
|
+
import { IcicleGraph } from './IcicleGraph';
|
|
30
31
|
var numberFormatter = new Intl.NumberFormat('en-US');
|
|
31
32
|
var ProfileIcicleGraph = function (_a) {
|
|
32
|
-
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize, navigateTo = _a.navigateTo, loading = _a.loading;
|
|
33
|
+
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize, navigateTo = _a.navigateTo, loading = _a.loading, setActionButtons = _a.setActionButtons;
|
|
33
34
|
var compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
|
|
34
35
|
var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
|
|
35
36
|
useEffect(function () {
|
|
@@ -55,11 +56,17 @@ var ProfileIcicleGraph = function (_a) {
|
|
|
55
56
|
numberFormatter.format(untrimmedTotal),
|
|
56
57
|
];
|
|
57
58
|
}, [graph]), isTrimmed = _c[0], _ = _c[1], trimmedPercentage = _c[2], formattedTotal = _c[3], formattedUntrimmedTotal = _c[4];
|
|
59
|
+
useEffect(function () {
|
|
60
|
+
if (setActionButtons === undefined) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
setActionButtons(_jsx(_Fragment, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setNewCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset View" })) }));
|
|
64
|
+
}, [setNewCurPath, curPath, setActionButtons]);
|
|
58
65
|
if (graph === undefined)
|
|
59
66
|
return _jsx("div", { children: "no data..." });
|
|
60
67
|
var total = graph.total;
|
|
61
68
|
if (parseFloat(total) === 0 && !loading)
|
|
62
69
|
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
63
|
-
return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}), isTrimmed ? (_jsxs("p", __assign({ className: "my-2 text-sm" }, { children: ["Showing ", formattedTotal, "(", trimmedPercentage, "%) out of ", formattedUntrimmedTotal, " samples"] }))) : null, _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit, navigateTo: navigateTo
|
|
70
|
+
return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}), isTrimmed ? (_jsxs("p", __assign({ className: "my-2 text-sm" }, { children: ["Showing ", formattedTotal, "(", trimmedPercentage, "%) out of ", formattedUntrimmedTotal, " samples"] }))) : null, _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit, navigateTo: navigateTo }) }))] })));
|
|
64
71
|
};
|
|
65
72
|
export default ProfileIcicleGraph;
|
|
@@ -93,6 +93,7 @@ var ProfileSelector = function (_a) {
|
|
|
93
93
|
var newValue = value.includes('\\') ? value.replaceAll('\\', '\\\\') : value;
|
|
94
94
|
var _a = Query.parse(queryExpressionString).setMatcher(key, newValue), newQuery = _a[0], changed = _a[1];
|
|
95
95
|
if (changed) {
|
|
96
|
+
// TODO: Change this to store the query object
|
|
96
97
|
setNewQueryExpression(newQuery.toString());
|
|
97
98
|
}
|
|
98
99
|
};
|
|
@@ -130,12 +131,21 @@ var ProfileSelector = function (_a) {
|
|
|
130
131
|
timeSelection: range.getRangeKey(),
|
|
131
132
|
});
|
|
132
133
|
}, addLabelMatcher: addLabelMatcher, onPointClick: function (timestamp, labels, queryExpression) {
|
|
134
|
+
// TODO: Pass the query object via click rather than queryExpression
|
|
135
|
+
var query = Query.parse(queryExpression);
|
|
136
|
+
labels.forEach(function (l) {
|
|
137
|
+
var _a = query.setMatcher(l.name, l.value), newQuery = _a[0], updated = _a[1];
|
|
138
|
+
if (updated) {
|
|
139
|
+
query = newQuery;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
133
142
|
var stepDuration = getStepDuration(querySelection.from, querySelection.to);
|
|
134
143
|
var stepDurationInMilliseconds = getStepDurationInMilliseconds(stepDuration);
|
|
135
|
-
var isDeltaType = Query.parse(queryExpression).profileType().delta;
|
|
136
144
|
var mergeFrom = timestamp;
|
|
137
|
-
var mergeTo =
|
|
138
|
-
|
|
145
|
+
var mergeTo = query.profileType().delta
|
|
146
|
+
? mergeFrom + stepDurationInMilliseconds
|
|
147
|
+
: mergeFrom;
|
|
148
|
+
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
|
|
139
149
|
} })) : (_jsx(_Fragment, { children: profileSelection == null && (_jsx("div", __assign({ className: "my-20 text-center" }, { children: _jsx("p", { children: "Run a query, and the result will be displayed here." }) }))) })) })] }));
|
|
140
150
|
};
|
|
141
151
|
export default ProfileSelector;
|
package/dist/ProfileSource.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Label, ProfileDiffSelection, QueryRequest } from '@parca/client';
|
|
2
|
-
import { ProfileType } from '@parca/parser';
|
|
2
|
+
import { ProfileType, Query } from '@parca/parser';
|
|
3
3
|
export interface ProfileSource {
|
|
4
4
|
QueryRequest: () => QueryRequest;
|
|
5
5
|
ProfileType: () => ProfileType;
|
|
@@ -30,10 +30,9 @@ export declare function ProfileSelectionFromParams(expression: string | undefine
|
|
|
30
30
|
export declare class MergedProfileSelection implements ProfileSelection {
|
|
31
31
|
mergeFrom: number;
|
|
32
32
|
mergeTo: number;
|
|
33
|
-
query:
|
|
33
|
+
query: Query;
|
|
34
34
|
filterQuery: string | undefined;
|
|
35
|
-
|
|
36
|
-
constructor(mergeFrom: number, mergeTo: number, labels: Label[], query: string, filterQuery?: string);
|
|
35
|
+
constructor(mergeFrom: number, mergeTo: number, query: Query, filterQuery?: string);
|
|
37
36
|
ProfileName(): string;
|
|
38
37
|
HistoryParams(): {
|
|
39
38
|
[key: string]: any;
|
|
@@ -55,14 +54,13 @@ export declare class ProfileDiffSource implements ProfileSource {
|
|
|
55
54
|
export declare class MergedProfileSource implements ProfileSource {
|
|
56
55
|
mergeFrom: number;
|
|
57
56
|
mergeTo: number;
|
|
58
|
-
|
|
59
|
-
query: string;
|
|
57
|
+
query: Query;
|
|
60
58
|
filterQuery: string | undefined;
|
|
61
|
-
constructor(mergeFrom: number, mergeTo: number,
|
|
59
|
+
constructor(mergeFrom: number, mergeTo: number, query: Query, filterQuery?: string);
|
|
62
60
|
DiffSelection(): ProfileDiffSelection;
|
|
63
61
|
QueryRequest(): QueryRequest;
|
|
64
62
|
ProfileType(): ProfileType;
|
|
65
63
|
Describe(): JSX.Element;
|
|
66
|
-
|
|
64
|
+
stringMatchers(): string[];
|
|
67
65
|
toString(): string;
|
|
68
66
|
}
|
package/dist/ProfileSource.js
CHANGED
|
@@ -30,7 +30,9 @@ export function SuffixParams(params, suffix) {
|
|
|
30
30
|
}));
|
|
31
31
|
}
|
|
32
32
|
export function ParseLabels(labels) {
|
|
33
|
-
return labels
|
|
33
|
+
return labels
|
|
34
|
+
.filter(function (str) { return str !== ''; })
|
|
35
|
+
.map(function (labelString) {
|
|
34
36
|
var parts = labelString.split('=', 2);
|
|
35
37
|
return { name: parts[0], value: parts[1] };
|
|
36
38
|
});
|
|
@@ -41,20 +43,27 @@ export function ProfileSelectionFromParams(expression, from, to, mergeFrom, merg
|
|
|
41
43
|
mergeFrom !== undefined &&
|
|
42
44
|
mergeTo !== undefined &&
|
|
43
45
|
expression !== undefined) {
|
|
44
|
-
|
|
46
|
+
// TODO: Refactor parsing the query and adding matchers
|
|
47
|
+
var query_1 = Query.parse(expression);
|
|
48
|
+
ParseLabels(labels !== null && labels !== void 0 ? labels : ['']).forEach(function (l) {
|
|
49
|
+
var _a = query_1.setMatcher(l.name, l.value), newQuery = _a[0], changed = _a[1];
|
|
50
|
+
if (changed) {
|
|
51
|
+
query_1 = newQuery;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return new MergedProfileSelection(parseInt(mergeFrom), parseInt(mergeTo), query_1, filterQuery);
|
|
45
55
|
}
|
|
46
56
|
return null;
|
|
47
57
|
}
|
|
48
58
|
var MergedProfileSelection = /** @class */ (function () {
|
|
49
|
-
function MergedProfileSelection(mergeFrom, mergeTo,
|
|
59
|
+
function MergedProfileSelection(mergeFrom, mergeTo, query, filterQuery) {
|
|
50
60
|
this.mergeFrom = mergeFrom;
|
|
51
61
|
this.mergeTo = mergeTo;
|
|
52
62
|
this.query = query;
|
|
53
63
|
this.filterQuery = filterQuery;
|
|
54
|
-
this.labels = labels;
|
|
55
64
|
}
|
|
56
65
|
MergedProfileSelection.prototype.ProfileName = function () {
|
|
57
|
-
return
|
|
66
|
+
return this.query.profileName();
|
|
58
67
|
};
|
|
59
68
|
MergedProfileSelection.prototype.HistoryParams = function () {
|
|
60
69
|
return {
|
|
@@ -62,14 +71,14 @@ var MergedProfileSelection = /** @class */ (function () {
|
|
|
62
71
|
merge_to: this.mergeTo.toString(),
|
|
63
72
|
query: this.query,
|
|
64
73
|
profile_name: this.ProfileName(),
|
|
65
|
-
labels: this.
|
|
74
|
+
labels: this.query.matchers.map(function (m) { return "".concat(m.key, "=").concat(encodeURIComponent(m.value)); }),
|
|
66
75
|
};
|
|
67
76
|
};
|
|
68
77
|
MergedProfileSelection.prototype.Type = function () {
|
|
69
78
|
return 'merge';
|
|
70
79
|
};
|
|
71
80
|
MergedProfileSelection.prototype.ProfileSource = function () {
|
|
72
|
-
return new MergedProfileSource(this.mergeFrom, this.mergeTo, this.
|
|
81
|
+
return new MergedProfileSource(this.mergeFrom, this.mergeTo, this.query, this.filterQuery);
|
|
73
82
|
};
|
|
74
83
|
return MergedProfileSelection;
|
|
75
84
|
}());
|
|
@@ -110,10 +119,9 @@ var ProfileDiffSource = /** @class */ (function () {
|
|
|
110
119
|
}());
|
|
111
120
|
export { ProfileDiffSource };
|
|
112
121
|
var MergedProfileSource = /** @class */ (function () {
|
|
113
|
-
function MergedProfileSource(mergeFrom, mergeTo,
|
|
122
|
+
function MergedProfileSource(mergeFrom, mergeTo, query, filterQuery) {
|
|
114
123
|
this.mergeFrom = mergeFrom;
|
|
115
124
|
this.mergeTo = mergeTo;
|
|
116
|
-
this.labels = labels;
|
|
117
125
|
this.query = query;
|
|
118
126
|
this.filterQuery = filterQuery;
|
|
119
127
|
}
|
|
@@ -124,7 +132,7 @@ var MergedProfileSource = /** @class */ (function () {
|
|
|
124
132
|
merge: {
|
|
125
133
|
start: Timestamp.fromDate(new Date(this.mergeFrom)),
|
|
126
134
|
end: Timestamp.fromDate(new Date(this.mergeTo)),
|
|
127
|
-
query: this.query,
|
|
135
|
+
query: this.query.toString(),
|
|
128
136
|
},
|
|
129
137
|
},
|
|
130
138
|
mode: ProfileDiffSelection_Mode.MERGE,
|
|
@@ -137,7 +145,7 @@ var MergedProfileSource = /** @class */ (function () {
|
|
|
137
145
|
merge: {
|
|
138
146
|
start: Timestamp.fromDate(new Date(this.mergeFrom)),
|
|
139
147
|
end: Timestamp.fromDate(new Date(this.mergeTo)),
|
|
140
|
-
query: this.query,
|
|
148
|
+
query: this.query.toString(),
|
|
141
149
|
},
|
|
142
150
|
},
|
|
143
151
|
reportType: QueryRequest_ReportType.FLAMEGRAPH_UNSPECIFIED,
|
|
@@ -146,18 +154,18 @@ var MergedProfileSource = /** @class */ (function () {
|
|
|
146
154
|
};
|
|
147
155
|
};
|
|
148
156
|
MergedProfileSource.prototype.ProfileType = function () {
|
|
149
|
-
return ProfileType.fromString(Query.parse(this.query).profileName());
|
|
157
|
+
return ProfileType.fromString(Query.parse(this.query.toString()).profileName());
|
|
150
158
|
};
|
|
151
159
|
MergedProfileSource.prototype.Describe = function () {
|
|
152
|
-
return (_jsxs("a", { children: ["Merge of \"", this.query, "\" from ", formatDate(this.mergeFrom, timeFormat),
|
|
160
|
+
return (_jsxs("a", { children: ["Merge of \"", this.query.toString(), "\" from ", formatDate(this.mergeFrom, timeFormat), ' ', "to ", formatDate(this.mergeTo, timeFormat)] }));
|
|
153
161
|
};
|
|
154
|
-
MergedProfileSource.prototype.
|
|
155
|
-
return this.
|
|
156
|
-
.filter(function (
|
|
157
|
-
.map(function (
|
|
162
|
+
MergedProfileSource.prototype.stringMatchers = function () {
|
|
163
|
+
return this.query.matchers
|
|
164
|
+
.filter(function (m) { return m.key !== '__name__'; })
|
|
165
|
+
.map(function (m) { return "".concat(m.key, "=").concat(m.value); });
|
|
158
166
|
};
|
|
159
167
|
MergedProfileSource.prototype.toString = function () {
|
|
160
|
-
return "merged profiles of query \"".concat(this.query, "\" from ").concat(formatDate(this.mergeFrom, timeFormat), " to ").concat(formatDate(this.mergeTo, timeFormat));
|
|
168
|
+
return "merged profiles of query \"".concat(this.query.toString(), "\" from ").concat(formatDate(this.mergeFrom, timeFormat), " to ").concat(formatDate(this.mergeTo, timeFormat));
|
|
161
169
|
};
|
|
162
170
|
return MergedProfileSource;
|
|
163
171
|
}());
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
|
|
3
|
+
import type { NavigateFunction } from '@parca/functions';
|
|
4
|
+
interface Props {
|
|
5
|
+
dashboardItem: string;
|
|
6
|
+
index: number;
|
|
7
|
+
isMultiPanelView: boolean;
|
|
8
|
+
handleClosePanel: (dashboardItem: string) => void;
|
|
9
|
+
navigateTo: NavigateFunction | undefined;
|
|
10
|
+
dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
|
|
11
|
+
getDashboardItemByType: (props: {
|
|
12
|
+
type: string;
|
|
13
|
+
isHalfScreen: boolean;
|
|
14
|
+
setActionButtons: (actionButtons: JSX.Element) => void;
|
|
15
|
+
}) => JSX.Element;
|
|
16
|
+
}
|
|
17
|
+
export declare const VisualizationPanel: React.NamedExoticComponent<Props>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
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 { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
// Copyright 2022 The Parca Authors
|
|
14
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
15
|
+
// you may not use this file except in compliance with the License.
|
|
16
|
+
// You may obtain a copy of the License at
|
|
17
|
+
//
|
|
18
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
19
|
+
//
|
|
20
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
21
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
22
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
23
|
+
// See the License for the specific language governing permissions and
|
|
24
|
+
// limitations under the License.
|
|
25
|
+
import React, { useState } from 'react';
|
|
26
|
+
import { Icon } from '@iconify/react';
|
|
27
|
+
import cx from 'classnames';
|
|
28
|
+
import { CloseIcon } from '@parca/icons';
|
|
29
|
+
import ViewSelector from './ViewSelector';
|
|
30
|
+
export var VisualizationPanel = React.memo(function VisualizationPanel(_a) {
|
|
31
|
+
var dashboardItem = _a.dashboardItem, index = _a.index, isMultiPanelView = _a.isMultiPanelView, handleClosePanel = _a.handleClosePanel, navigateTo = _a.navigateTo, dragHandleProps = _a.dragHandleProps, getDashboardItemByType = _a.getDashboardItemByType;
|
|
32
|
+
var _b = useState(_jsx(_Fragment, {})), actionButtons = _b[0], setActionButtons = _b[1];
|
|
33
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", __assign({ className: "w-full flex justify-end pb-2" }, { children: [_jsxs("div", __assign({ className: "w-full flex justify-between items-center" }, { children: [_jsxs("div", __assign({ className: "flex" }, { children: [_jsx("div", __assign({ className: cx(isMultiPanelView ? 'visible' : 'invisible', 'flex items-center') }, dragHandleProps, { children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) })), _jsx(_Fragment, { children: actionButtons })] })), _jsx(ViewSelector, { defaultValue: dashboardItem, navigateTo: navigateTo, position: index })] })), isMultiPanelView && (_jsx("button", __assign({ type: "button", onClick: function () { return handleClosePanel(dashboardItem); }, className: "pl-2" }, { children: _jsx(CloseIcon, {}) })))] })), getDashboardItemByType({
|
|
34
|
+
type: dashboardItem,
|
|
35
|
+
isHalfScreen: isMultiPanelView,
|
|
36
|
+
setActionButtons: setActionButtons,
|
|
37
|
+
})] }));
|
|
38
|
+
});
|
|
@@ -33,14 +33,12 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
|
|
|
33
33
|
// See the License for the specific language governing permissions and
|
|
34
34
|
// limitations under the License.
|
|
35
35
|
import { Profiler, useEffect, useMemo, useState } from 'react';
|
|
36
|
-
import { Icon } from '@iconify/react';
|
|
37
36
|
import cx from 'classnames';
|
|
38
37
|
import { scaleLinear } from 'd3';
|
|
39
38
|
import { DragDropContext, Draggable, Droppable, } from 'react-beautiful-dnd';
|
|
40
39
|
import { Button, Card, ConditionalWrapper, KeyDownProvider, useParcaContext, useURLState, } from '@parca/components';
|
|
41
40
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
42
41
|
import { getNewSpanColor } from '@parca/functions';
|
|
43
|
-
import { CloseIcon } from '@parca/icons';
|
|
44
42
|
import { selectDarkMode, useAppSelector } from '@parca/store';
|
|
45
43
|
import { Callgraph } from '../';
|
|
46
44
|
import ProfileIcicleGraph from '../ProfileIcicleGraph';
|
|
@@ -49,6 +47,7 @@ import ProfileShareButton from '../components/ProfileShareButton';
|
|
|
49
47
|
import useDelayedLoader from '../useDelayedLoader';
|
|
50
48
|
import FilterByFunctionButton from './FilterByFunctionButton';
|
|
51
49
|
import ViewSelector from './ViewSelector';
|
|
50
|
+
import { VisualizationPanel } from './VisualizationPanel';
|
|
52
51
|
function arrayEquals(a, b) {
|
|
53
52
|
return (Array.isArray(a) &&
|
|
54
53
|
Array.isArray(b) &&
|
|
@@ -63,6 +62,7 @@ export var ProfileView = function (_a) {
|
|
|
63
62
|
param: 'dashboard_items',
|
|
64
63
|
navigateTo: navigateTo,
|
|
65
64
|
}), rawDashboardItems = _d[0], setDashboardItems = _d[1];
|
|
65
|
+
var currentSearchString = useURLState({ param: 'search_string' })[0];
|
|
66
66
|
var dashboardItems = rawDashboardItems;
|
|
67
67
|
var isDarkMode = useAppSelector(selectDarkMode);
|
|
68
68
|
var isMultiPanelView = dashboardItems.length > 1;
|
|
@@ -97,19 +97,19 @@ export var ProfileView = function (_a) {
|
|
|
97
97
|
var minColor = scaleLinear([isDarkMode ? 'black' : 'white', maxColor])(0.3);
|
|
98
98
|
var colorRange = [minColor, maxColor];
|
|
99
99
|
var getDashboardItemByType = function (_a) {
|
|
100
|
-
var type = _a.type, isHalfScreen = _a.isHalfScreen;
|
|
100
|
+
var type = _a.type, isHalfScreen = _a.isHalfScreen, setActionButtons = _a.setActionButtons;
|
|
101
101
|
switch (type) {
|
|
102
102
|
case 'icicle': {
|
|
103
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
104
|
id: 'icicleGraph',
|
|
105
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: " " }));
|
|
106
|
+
} }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) }))) : (_jsx(_Fragment, { children: " " }));
|
|
107
107
|
}
|
|
108
108
|
case 'callgraph': {
|
|
109
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, {}));
|
|
110
110
|
}
|
|
111
111
|
case 'table': {
|
|
112
|
-
return topTableData != null ? (_jsx(TopTable, { loading: topTableData.loading, data: topTableData.data, sampleUnit: sampleUnit, navigateTo: navigateTo })) : (_jsx(_Fragment, {}));
|
|
112
|
+
return topTableData != null ? (_jsx(TopTable, { loading: topTableData.loading, data: topTableData.data, sampleUnit: sampleUnit, navigateTo: navigateTo, setActionButtons: setActionButtons, currentSearchString: currentSearchString })) : (_jsx(_Fragment, {}));
|
|
113
113
|
}
|
|
114
114
|
default: {
|
|
115
115
|
return _jsx(_Fragment, {});
|
|
@@ -135,10 +135,6 @@ export var ProfileView = function (_a) {
|
|
|
135
135
|
onDownloadPProf();
|
|
136
136
|
} }, { children: "Download pprof" }))] })), _jsx(FilterByFunctionButton, { navigateTo: navigateTo })] })), _jsx("div", __assign({ className: "flex ml-auto gap-2" }, { children: _jsx(ViewSelector, { defaultValue: "", navigateTo: navigateTo, position: -1, placeholderText: "Add panel...", primary: true, addView: true, disabled: isMultiPanelView || dashboardItems.length < 1 }) }))] })), isLoaderVisible ? (_jsx(_Fragment, { children: loader })) : (_jsx(DragDropContext, __assign({ onDragEnd: onDragEnd }, { children: _jsx("div", __assign({ className: "w-full", ref: ref }, { children: _jsx(Droppable, __assign({ droppableId: "droppable", direction: "horizontal" }, { children: function (provided) { return (_jsx("div", __assign({ ref: provided.innerRef, className: "flex space-x-4 justify-between w-full" }, provided.droppableProps, { children: dashboardItems.map(function (dashboardItem, index) {
|
|
137
137
|
return (_jsx(Draggable, __assign({ draggableId: dashboardItem, index: index, isDragDisabled: !isMultiPanelView }, { children: function (provided, snapshot) { return (_createElement("div", __assign({ ref: provided.innerRef }, provided.draggableProps, { key: dashboardItem, className: cx('border dark:bg-gray-700 rounded border-gray-300 dark:border-gray-500 p-3', isMultiPanelView ? 'w-1/2' : 'w-full', snapshot.isDragging ? 'bg-gray-200' : 'bg-white') }),
|
|
138
|
-
|
|
139
|
-
getDashboardItemByType({
|
|
140
|
-
type: dashboardItem,
|
|
141
|
-
isHalfScreen: isMultiPanelView,
|
|
142
|
-
}))); } }), dashboardItem));
|
|
138
|
+
_jsx(VisualizationPanel, { handleClosePanel: handleClosePanel, isMultiPanelView: isMultiPanelView, dashboardItem: dashboardItem, getDashboardItemByType: getDashboardItemByType, dragHandleProps: provided.dragHandleProps, navigateTo: navigateTo, index: index }))); } }), dashboardItem));
|
|
143
139
|
}) }))); } })) })) })))] }) }) })) }));
|
|
144
140
|
};
|
package/dist/TopTable/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import { Top, TopNodeMeta } from '@parca/client';
|
|
2
3
|
import { type NavigateFunction } from '@parca/functions';
|
|
3
4
|
interface TopTableProps {
|
|
@@ -5,7 +6,9 @@ interface TopTableProps {
|
|
|
5
6
|
data?: Top;
|
|
6
7
|
sampleUnit: string;
|
|
7
8
|
navigateTo?: NavigateFunction;
|
|
9
|
+
currentSearchString?: string;
|
|
10
|
+
setActionButtons?: (buttons: JSX.Element) => void;
|
|
8
11
|
}
|
|
9
12
|
export declare const RowLabel: (meta: TopNodeMeta | undefined) => string;
|
|
10
|
-
export declare const TopTable:
|
|
13
|
+
export declare const TopTable: React.NamedExoticComponent<TopTableProps>;
|
|
11
14
|
export default TopTable;
|
package/dist/TopTable/index.js
CHANGED
|
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
9
9
|
};
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx, Fragment as _Fragment
|
|
12
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
13
|
// Copyright 2022 The Parca Authors
|
|
14
14
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
15
15
|
// you may not use this file except in compliance with the License.
|
|
@@ -22,7 +22,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
22
22
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
23
23
|
// See the License for the specific language governing permissions and
|
|
24
24
|
// limitations under the License.
|
|
25
|
-
import { useCallback, useMemo } from 'react';
|
|
25
|
+
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
26
26
|
import { createColumnHelper } from '@tanstack/react-table';
|
|
27
27
|
import { Button, Table, useURLState } from '@parca/components';
|
|
28
28
|
import { getLastItem, isSearchMatch, parseParams, valueFormatter, } from '@parca/functions';
|
|
@@ -47,12 +47,11 @@ var addPlusSign = function (num) {
|
|
|
47
47
|
}
|
|
48
48
|
return "+".concat(num);
|
|
49
49
|
};
|
|
50
|
-
export var TopTable = function (_a) {
|
|
50
|
+
export var TopTable = React.memo(function TopTable(_a) {
|
|
51
51
|
var _b;
|
|
52
|
-
var top = _a.data, unit = _a.sampleUnit, navigateTo = _a.navigateTo, loading = _a.loading;
|
|
52
|
+
var top = _a.data, unit = _a.sampleUnit, navigateTo = _a.navigateTo, loading = _a.loading, currentSearchString = _a.currentSearchString, setActionButtons = _a.setActionButtons;
|
|
53
53
|
var router = parseParams(window.location.search);
|
|
54
54
|
var rawDashboardItems = useURLState({ param: 'dashboard_items' })[0];
|
|
55
|
-
var currentSearchString = useURLState({ param: 'search_string' })[0];
|
|
56
55
|
var rawcompareMode = useURLState({ param: 'compare_a' })[0];
|
|
57
56
|
var compareMode = rawcompareMode === undefined ? false : rawcompareMode === 'true';
|
|
58
57
|
var dashboardItems = rawDashboardItems;
|
|
@@ -135,12 +134,18 @@ export var TopTable = function (_a) {
|
|
|
135
134
|
navigateTo('/', __assign(__assign({}, router), { search_string: '' }), { replace: true });
|
|
136
135
|
}
|
|
137
136
|
}, [navigateTo, router]);
|
|
137
|
+
useEffect(function () {
|
|
138
|
+
if (setActionButtons === undefined) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
setActionButtons(dashboardItems.length > 1 ? (_jsx(Button, __assign({ color: "neutral", onClick: clearSelection, className: "w-auto", variant: "neutral", disabled: currentSearchString === undefined || currentSearchString.length === 0 }, { children: "Clear selection" }))) : (_jsx(_Fragment, {})));
|
|
142
|
+
}, [dashboardItems, clearSelection, currentSearchString, setActionButtons]);
|
|
138
143
|
var initialSorting = useMemo(function () {
|
|
139
144
|
return [{ id: compareMode ? 'diff' : 'cumulative', desc: true }];
|
|
140
145
|
}, [compareMode]);
|
|
141
146
|
var total = top != null ? top.list.length : 0;
|
|
142
147
|
if (total === 0 && !loading)
|
|
143
148
|
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
144
|
-
return (
|
|
145
|
-
};
|
|
149
|
+
return (_jsx("div", __assign({ className: "relative" }, { children: _jsx("div", __assign({ className: "w-full font-robotoMono h-[80vh] overflow-scroll" }, { children: _jsx(Table, { data: (_b = top === null || top === void 0 ? void 0 : top.list) !== null && _b !== void 0 ? _b : [], columns: columns, initialSorting: initialSorting, onRowClick: onRowClick, enableHighlighting: enableHighlighting, shouldHighlightRow: shouldHighlightRow, usePointerCursor: dashboardItems.length > 1 }) })) })));
|
|
150
|
+
});
|
|
146
151
|
export default TopTable;
|