@parca/profile 0.16.64 → 0.16.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/MatchersInput/index.js +2 -2
- package/dist/ProfileMetricsGraph/index.js +2 -2
- package/dist/ProfileView.js +6 -6
- package/dist/ProfileViewWithData.js +9 -1
- package/dist/useQuery.js +0 -1
- package/package.json +3 -3
- package/src/MatchersInput/index.tsx +3 -2
- package/src/ProfileMetricsGraph/index.tsx +2 -2
- package/src/ProfileView.tsx +13 -11
- package/src/ProfileViewWithData.tsx +10 -1
- package/src/useQuery.tsx +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 0.16.65 (2022-11-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
6
10
|
## [0.16.64](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.63...@parca/profile@0.16.64) (2022-11-08)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -27,7 +27,7 @@ import { Transition } from '@headlessui/react';
|
|
|
27
27
|
import { Query } from '@parca/parser';
|
|
28
28
|
import { usePopper } from 'react-popper';
|
|
29
29
|
import cx from 'classnames';
|
|
30
|
-
import {
|
|
30
|
+
import { useParcaContext, useGrpcMetadata } from '@parca/components';
|
|
31
31
|
export var useLabelNames = function (client) {
|
|
32
32
|
var _a = useState(true), loading = _a[0], setLoading = _a[1];
|
|
33
33
|
var _b = useState({}), result = _b[0], setResult = _b[1];
|
|
@@ -73,7 +73,7 @@ var MatchersInput = function (_a) {
|
|
|
73
73
|
placement: 'bottom-start',
|
|
74
74
|
}), styles = _l.styles, attributes = _l.attributes;
|
|
75
75
|
var metadata = useGrpcMetadata();
|
|
76
|
-
var Spinner =
|
|
76
|
+
var Spinner = useParcaContext().loader;
|
|
77
77
|
var _m = useLabelNames(queryClient), labelNamesLoading = _m.loading, result = _m.result;
|
|
78
78
|
var labelNamesResponse = result.response, labelNamesError = result.error;
|
|
79
79
|
var LoadingSpinner = function () {
|
|
@@ -62,7 +62,7 @@ import { useState, useEffect } from 'react';
|
|
|
62
62
|
import MetricsGraph from '../MetricsGraph';
|
|
63
63
|
import { SingleProfileSelection } from '..';
|
|
64
64
|
import { Timestamp } from '@parca/client';
|
|
65
|
-
import { useGrpcMetadata,
|
|
65
|
+
import { useGrpcMetadata, useParcaContext } from '@parca/components';
|
|
66
66
|
import { Query } from '@parca/parser';
|
|
67
67
|
import useDelayedLoader from '../useDelayedLoader';
|
|
68
68
|
export var useQueryRange = function (client, queryExpression, start, end) {
|
|
@@ -100,7 +100,7 @@ var ProfileMetricsGraph = function (_a) {
|
|
|
100
100
|
var queryClient = _a.queryClient, queryExpression = _a.queryExpression, profile = _a.profile, from = _a.from, to = _a.to, select = _a.select, setTimeRange = _a.setTimeRange, addLabelMatcher = _a.addLabelMatcher;
|
|
101
101
|
var _b = useQueryRange(queryClient, queryExpression, from, to), isLoading = _b.isLoading, response = _b.response, error = _b.error;
|
|
102
102
|
var isLoaderVisible = useDelayedLoader(isLoading);
|
|
103
|
-
var loader =
|
|
103
|
+
var loader = useParcaContext().loader;
|
|
104
104
|
if (isLoaderVisible) {
|
|
105
105
|
return _jsx(_Fragment, { children: loader });
|
|
106
106
|
}
|
package/dist/ProfileView.js
CHANGED
|
@@ -22,18 +22,18 @@ import { Fragment as _Fragment, jsx as _jsx, 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 { useEffect, useMemo, useState } from 'react';
|
|
25
|
+
import { Profiler, useEffect, useMemo, useState } from 'react';
|
|
26
|
+
import { scaleLinear } from 'd3';
|
|
26
27
|
import { getNewSpanColor, parseParams } from '@parca/functions';
|
|
27
28
|
import useUIFeatureFlag from '@parca/functions/useUIFeatureFlag';
|
|
28
|
-
import { Button, Card, SearchNodes,
|
|
29
|
-
import { Callgraph } from './';
|
|
29
|
+
import { Button, Card, SearchNodes, useParcaContext } from '@parca/components';
|
|
30
30
|
import { useContainerDimensions } from '@parca/dynamicsize';
|
|
31
31
|
import { useAppSelector, selectDarkMode, selectSearchNodeString } from '@parca/store';
|
|
32
|
+
import { Callgraph } from './';
|
|
32
33
|
import ProfileShareButton from './components/ProfileShareButton';
|
|
33
34
|
import ProfileIcicleGraph from './ProfileIcicleGraph';
|
|
34
35
|
import TopTable from './TopTable';
|
|
35
36
|
import useDelayedLoader from './useDelayedLoader';
|
|
36
|
-
import { scaleLinear } from 'd3';
|
|
37
37
|
import './ProfileView.styles.css';
|
|
38
38
|
function arrayEquals(a, b) {
|
|
39
39
|
return (Array.isArray(a) &&
|
|
@@ -63,7 +63,7 @@ export var ProfileView = function (_a) {
|
|
|
63
63
|
var isDarkMode = useAppSelector(selectDarkMode);
|
|
64
64
|
var currentSearchString = useAppSelector(selectSearchNodeString);
|
|
65
65
|
var callgraphEnabled = useUIFeatureFlag('callgraph')[0];
|
|
66
|
-
var
|
|
66
|
+
var _d = useParcaContext(), loader = _d.loader, perf = _d.perf;
|
|
67
67
|
useEffect(function () {
|
|
68
68
|
// Reset the current path when the profile source changes
|
|
69
69
|
setCurPath([]);
|
|
@@ -115,5 +115,5 @@ export var ProfileView = function (_a) {
|
|
|
115
115
|
return (_jsx(_Fragment, { children: _jsx("div", __assign({ className: "py-3" }, { children: _jsx(Card, { children: _jsxs(Card.Body, { children: [_jsxs("div", __assign({ className: "flex py-3 w-full" }, { children: [_jsxs("div", __assign({ className: "w-2/5 flex space-x-4" }, { children: [_jsxs("div", __assign({ className: "flex space-x-1" }, { children: [profileSource != null && queryClient != null ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient })) : null, _jsx(Button, __assign({ color: "neutral", onClick: function (e) {
|
|
116
116
|
e.preventDefault();
|
|
117
117
|
onDownloadPProf();
|
|
118
|
-
} }, { children: "Download pprof" }))] })), _jsx(SearchNodes, {})] })), _jsxs("div", __assign({ className: "flex ml-auto" }, { children: [_jsx("div", __assign({ className: "mr-3" }, { children: _jsx(Button, __assign({ color: "neutral", onClick: resetIcicleGraph, disabled: curPath.length === 0, className: "whitespace-nowrap text-ellipsis" }, { children: "Reset View" })) })), callgraphEnabled ? (_jsx("div", __assign({ className: "mr-3" }, { children: _jsx(Button, __assign({ variant: "".concat(currentView === 'callgraph' ? 'primary' : 'neutral'), onClick: function () { return switchProfileView('callgraph'); }, className: "whitespace-nowrap text-ellipsis" }, { children: "Callgraph" })) }))) : null, _jsx(Button, __assign({ variant: "".concat(currentView === 'table' ? 'primary' : 'neutral'), className: "items-center rounded-tr-none rounded-br-none w-auto px-8 whitespace-nowrap text-ellipsis no-outline-on-buttons", onClick: function () { return switchProfileView('table'); } }, { children: "Table" })), _jsx(Button, __assign({ variant: "".concat(currentView === 'both' ? 'primary' : 'neutral'), className: "items-center rounded-tl-none rounded-tr-none rounded-bl-none rounded-br-none border-l-0 border-r-0 w-auto px-8 whitespace-nowrap no-outline-on-buttons text-ellipsis", onClick: function () { return switchProfileView('both'); } }, { children: "Both" })), _jsx(Button, __assign({ variant: "".concat(currentView === 'icicle' ? 'primary' : 'neutral'), className: "items-center rounded-tl-none rounded-bl-none w-auto px-8 whitespace-nowrap text-ellipsis no-outline-on-buttons", onClick: function () { return switchProfileView('icicle'); } }, { children: "Icicle Graph" }))] }))] })), _jsxs("div", __assign({ ref: ref, className: "flex space-x-4 justify-between w-full" }, { children: [currentView === 'icicle' && (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null && (_jsx("div", __assign({ className: "w-full" }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit }) }))), currentView === 'callgraph' && (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) != null && (_jsx("div", __assign({ className: "w-full" }, { children: (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) !== undefined && (_jsx(Callgraph, { graph: callgraphData.data, sampleUnit: sampleUnit, width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, colorRange: colorRange })) }))), currentView === 'table' && topTableData != null && (_jsx("div", __assign({ className: "w-full" }, { children: _jsx(TopTable, { data: topTableData.data, sampleUnit: sampleUnit }) }))), currentView === 'both' && (_jsxs(_Fragment, { children: [_jsx("div", __assign({ className: "w-1/2" }, { children: _jsx(TopTable, { data: topTableData === null || topTableData === void 0 ? void 0 : topTableData.data, sampleUnit: sampleUnit }) })), _jsx("div", __assign({ className: "w-1/2" }, { children: flamegraphData != null && (_jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit })) }))] }))] }))] }) }) })) }));
|
|
118
|
+
} }, { children: "Download pprof" }))] })), _jsx(SearchNodes, {})] })), _jsxs("div", __assign({ className: "flex ml-auto" }, { children: [_jsx("div", __assign({ className: "mr-3" }, { children: _jsx(Button, __assign({ color: "neutral", onClick: resetIcicleGraph, disabled: curPath.length === 0, className: "whitespace-nowrap text-ellipsis" }, { children: "Reset View" })) })), callgraphEnabled ? (_jsx("div", __assign({ className: "mr-3" }, { children: _jsx(Button, __assign({ variant: "".concat(currentView === 'callgraph' ? 'primary' : 'neutral'), onClick: function () { return switchProfileView('callgraph'); }, className: "whitespace-nowrap text-ellipsis" }, { children: "Callgraph" })) }))) : null, _jsx(Button, __assign({ variant: "".concat(currentView === 'table' ? 'primary' : 'neutral'), className: "items-center rounded-tr-none rounded-br-none w-auto px-8 whitespace-nowrap text-ellipsis no-outline-on-buttons", onClick: function () { return switchProfileView('table'); } }, { children: "Table" })), _jsx(Button, __assign({ variant: "".concat(currentView === 'both' ? 'primary' : 'neutral'), className: "items-center rounded-tl-none rounded-tr-none rounded-bl-none rounded-br-none border-l-0 border-r-0 w-auto px-8 whitespace-nowrap no-outline-on-buttons text-ellipsis", onClick: function () { return switchProfileView('both'); } }, { children: "Both" })), _jsx(Button, __assign({ variant: "".concat(currentView === 'icicle' ? 'primary' : 'neutral'), className: "items-center rounded-tl-none rounded-bl-none w-auto px-8 whitespace-nowrap text-ellipsis no-outline-on-buttons", onClick: function () { return switchProfileView('icicle'); } }, { children: "Icicle Graph" }))] }))] })), _jsxs("div", __assign({ ref: ref, className: "flex space-x-4 justify-between w-full" }, { children: [currentView === 'icicle' && (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null && (_jsx("div", __assign({ className: "w-full" }, { children: _jsx(Profiler, __assign({ id: "icicleGraph", onRender: perf.onRender }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit }) })) }))), currentView === 'callgraph' && (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) != null && (_jsx("div", __assign({ className: "w-full" }, { children: (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) !== undefined && (_jsx(Callgraph, { graph: callgraphData.data, sampleUnit: sampleUnit, width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, colorRange: colorRange })) }))), currentView === 'table' && topTableData != null && (_jsx("div", __assign({ className: "w-full" }, { children: _jsx(TopTable, { data: topTableData.data, sampleUnit: sampleUnit }) }))), currentView === 'both' && (_jsxs(_Fragment, { children: [_jsx("div", __assign({ className: "w-1/2" }, { children: _jsx(TopTable, { data: topTableData === null || topTableData === void 0 ? void 0 : topTableData.data, sampleUnit: sampleUnit }) })), _jsx("div", __assign({ className: "w-1/2" }, { children: flamegraphData != null && (_jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit })) }))] }))] }))] }) }) })) }));
|
|
119
119
|
};
|
|
@@ -51,8 +51,9 @@ import { QueryRequest_ReportType } from '@parca/client';
|
|
|
51
51
|
import { useQuery } from './useQuery';
|
|
52
52
|
import { ProfileView, useProfileVisState } from './ProfileView';
|
|
53
53
|
import { downloadPprof } from './utils';
|
|
54
|
-
import { useGrpcMetadata } from '@parca/components';
|
|
54
|
+
import { useGrpcMetadata, useParcaContext } from '@parca/components';
|
|
55
55
|
import { saveAsBlob } from '@parca/functions';
|
|
56
|
+
import { useEffect } from 'react';
|
|
56
57
|
export var ProfileViewWithData = function (_a) {
|
|
57
58
|
var _b, _c;
|
|
58
59
|
var queryClient = _a.queryClient, profileSource = _a.profileSource, navigateTo = _a.navigateTo;
|
|
@@ -62,6 +63,13 @@ export var ProfileViewWithData = function (_a) {
|
|
|
62
63
|
var _d = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_TABLE, {
|
|
63
64
|
skip: currentView !== 'icicle' && currentView !== 'both',
|
|
64
65
|
}), flamegraphLoading = _d.isLoading, flamegraphResponse = _d.response, flamegraphError = _d.error;
|
|
66
|
+
var perf = useParcaContext().perf;
|
|
67
|
+
useEffect(function () {
|
|
68
|
+
if (flamegraphLoading) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
perf.markInteraction('Flamegraph Render');
|
|
72
|
+
}, [flamegraphLoading, flamegraphResponse, perf]);
|
|
65
73
|
var _e = useQuery(queryClient, profileSource, QueryRequest_ReportType.TOP, {
|
|
66
74
|
skip: currentView !== 'table' && currentView !== 'both',
|
|
67
75
|
}), topTableLoading = _e.isLoading, topTableResponse = _e.response, topTableError = _e.error;
|
package/dist/useQuery.js
CHANGED
|
@@ -30,7 +30,6 @@ export var useQuery = function (client, profileSource, reportType, options) {
|
|
|
30
30
|
isLoading: true,
|
|
31
31
|
});
|
|
32
32
|
var req = profileSource.QueryRequest();
|
|
33
|
-
console.log('req', req);
|
|
34
33
|
req.reportType = reportType;
|
|
35
34
|
var call = client.query(req, { meta: metadata });
|
|
36
35
|
call.response
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.65",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@iconify/react": "^3.2.2",
|
|
7
7
|
"@parca/client": "^0.16.54",
|
|
8
|
-
"@parca/components": "^0.16.
|
|
8
|
+
"@parca/components": "^0.16.60",
|
|
9
9
|
"@parca/dynamicsize": "^0.16.51",
|
|
10
10
|
"@parca/functions": "^0.16.51",
|
|
11
11
|
"@parca/parser": "^0.16.50",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"access": "public",
|
|
41
41
|
"registry": "https://registry.npmjs.org/"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "0b1285b6be9aee7b2716d230e1d4bdc5a0cea4d2"
|
|
44
44
|
}
|
|
@@ -17,7 +17,8 @@ import {Query} from '@parca/parser';
|
|
|
17
17
|
import {LabelsResponse, QueryServiceClient} from '@parca/client';
|
|
18
18
|
import {usePopper} from 'react-popper';
|
|
19
19
|
import cx from 'classnames';
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
import {useParcaContext, useGrpcMetadata} from '@parca/components';
|
|
21
22
|
|
|
22
23
|
interface MatchersInputProps {
|
|
23
24
|
queryClient: QueryServiceClient;
|
|
@@ -97,7 +98,7 @@ const MatchersInput = ({
|
|
|
97
98
|
placement: 'bottom-start',
|
|
98
99
|
});
|
|
99
100
|
const metadata = useGrpcMetadata();
|
|
100
|
-
const {loader: Spinner} =
|
|
101
|
+
const {loader: Spinner} = useParcaContext();
|
|
101
102
|
|
|
102
103
|
const {loading: labelNamesLoading, result} = useLabelNames(queryClient);
|
|
103
104
|
const {response: labelNamesResponse, error: labelNamesError} = result;
|
|
@@ -16,7 +16,7 @@ import MetricsGraph from '../MetricsGraph';
|
|
|
16
16
|
import {ProfileSelection, SingleProfileSelection} from '..';
|
|
17
17
|
import {QueryServiceClient, QueryRangeResponse, Label, Timestamp} from '@parca/client';
|
|
18
18
|
import {RpcError} from '@protobuf-ts/runtime-rpc';
|
|
19
|
-
import {DateTimeRange, useGrpcMetadata,
|
|
19
|
+
import {DateTimeRange, useGrpcMetadata, useParcaContext} from '@parca/components';
|
|
20
20
|
import {Query} from '@parca/parser';
|
|
21
21
|
import useDelayedLoader from '../useDelayedLoader';
|
|
22
22
|
|
|
@@ -89,7 +89,7 @@ const ProfileMetricsGraph = ({
|
|
|
89
89
|
}: ProfileMetricsGraphProps): JSX.Element => {
|
|
90
90
|
const {isLoading, response, error} = useQueryRange(queryClient, queryExpression, from, to);
|
|
91
91
|
const isLoaderVisible = useDelayedLoader(isLoading);
|
|
92
|
-
const {loader} =
|
|
92
|
+
const {loader} = useParcaContext();
|
|
93
93
|
|
|
94
94
|
if (isLoaderVisible) {
|
|
95
95
|
return <>{loader}</>;
|
package/src/ProfileView.tsx
CHANGED
|
@@ -11,22 +11,22 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import {Profiler, useEffect, useMemo, useState} from 'react';
|
|
15
|
+
import {scaleLinear} from 'd3';
|
|
15
16
|
|
|
16
17
|
import {getNewSpanColor, parseParams} from '@parca/functions';
|
|
17
18
|
import useUIFeatureFlag from '@parca/functions/useUIFeatureFlag';
|
|
18
19
|
import {QueryServiceClient, Flamegraph, Top, Callgraph as CallgraphType} from '@parca/client';
|
|
19
|
-
import {Button, Card, SearchNodes,
|
|
20
|
-
import {Callgraph} from './';
|
|
20
|
+
import {Button, Card, SearchNodes, useParcaContext} from '@parca/components';
|
|
21
21
|
import {useContainerDimensions} from '@parca/dynamicsize';
|
|
22
22
|
import {useAppSelector, selectDarkMode, selectSearchNodeString} from '@parca/store';
|
|
23
23
|
|
|
24
|
+
import {Callgraph} from './';
|
|
24
25
|
import ProfileShareButton from './components/ProfileShareButton';
|
|
25
26
|
import ProfileIcicleGraph from './ProfileIcicleGraph';
|
|
26
27
|
import {ProfileSource} from './ProfileSource';
|
|
27
28
|
import TopTable from './TopTable';
|
|
28
29
|
import useDelayedLoader from './useDelayedLoader';
|
|
29
|
-
import {scaleLinear} from 'd3';
|
|
30
30
|
|
|
31
31
|
import './ProfileView.styles.css';
|
|
32
32
|
|
|
@@ -114,7 +114,7 @@ export const ProfileView = ({
|
|
|
114
114
|
|
|
115
115
|
const [callgraphEnabled] = useUIFeatureFlag('callgraph');
|
|
116
116
|
|
|
117
|
-
const {loader} =
|
|
117
|
+
const {loader, perf} = useParcaContext();
|
|
118
118
|
|
|
119
119
|
useEffect(() => {
|
|
120
120
|
// Reset the current path when the profile source changes
|
|
@@ -265,12 +265,14 @@ export const ProfileView = ({
|
|
|
265
265
|
<div ref={ref} className="flex space-x-4 justify-between w-full">
|
|
266
266
|
{currentView === 'icicle' && flamegraphData?.data != null && (
|
|
267
267
|
<div className="w-full">
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
<Profiler id="icicleGraph" onRender={perf.onRender}>
|
|
269
|
+
<ProfileIcicleGraph
|
|
270
|
+
curPath={curPath}
|
|
271
|
+
setNewCurPath={setNewCurPath}
|
|
272
|
+
graph={flamegraphData.data}
|
|
273
|
+
sampleUnit={sampleUnit}
|
|
274
|
+
/>
|
|
275
|
+
</Profiler>
|
|
274
276
|
</div>
|
|
275
277
|
)}
|
|
276
278
|
{currentView === 'callgraph' && callgraphData?.data != null && (
|
|
@@ -17,8 +17,9 @@ import {useQuery} from './useQuery';
|
|
|
17
17
|
import {ProfileView, useProfileVisState} from './ProfileView';
|
|
18
18
|
import {ProfileSource} from './ProfileSource';
|
|
19
19
|
import {downloadPprof} from './utils';
|
|
20
|
-
import {useGrpcMetadata} from '@parca/components';
|
|
20
|
+
import {useGrpcMetadata, useParcaContext} from '@parca/components';
|
|
21
21
|
import {saveAsBlob} from '@parca/functions';
|
|
22
|
+
import {useEffect} from 'react';
|
|
22
23
|
|
|
23
24
|
type NavigateFunction = (path: string, queryParams: any) => void;
|
|
24
25
|
|
|
@@ -44,6 +45,14 @@ export const ProfileViewWithData = ({
|
|
|
44
45
|
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_TABLE, {
|
|
45
46
|
skip: currentView !== 'icicle' && currentView !== 'both',
|
|
46
47
|
});
|
|
48
|
+
const {perf} = useParcaContext();
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (flamegraphLoading) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
perf.markInteraction('Flamegraph Render');
|
|
55
|
+
}, [flamegraphLoading, flamegraphResponse, perf]);
|
|
47
56
|
|
|
48
57
|
const {
|
|
49
58
|
isLoading: topTableLoading,
|