@parca/profile 0.14.16 → 0.14.31
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 +34 -0
- package/package.json +4 -4
- package/src/IcicleGraph.tsx +19 -2
- package/src/ProfileIcicleGraph.tsx +13 -0
- package/src/ProfileSource.tsx +13 -0
- package/src/ProfileView.tsx +20 -7
- package/src/ProfileViewWithData.tsx +15 -2
- package/src/TopTable.tsx +35 -14
- package/src/__tests__/suffix_params.test.ts +13 -0
- package/src/components/DiffLegend.tsx +15 -2
- package/src/components/ProfileShareButton/ResultBox.tsx +13 -0
- package/src/components/ProfileShareButton/index.tsx +15 -2
- package/src/index.tsx +13 -0
- package/src/useDelayedLoader.ts +16 -3
- package/src/useQuery.tsx +17 -4
- package/src/utils.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,40 @@
|
|
|
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.14.31](https://github.com/parca-dev/parca/compare/ui-v0.14.30...ui-v0.14.31) (2022-08-18)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **ui:** address all problems reported by ESLint ([7f9c921](https://github.com/parca-dev/parca/commit/7f9c9217af49f2661a4363b9b17a9a06f1c7539b))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## [0.14.30](https://github.com/parca-dev/parca/compare/ui-v0.14.29...ui-v0.14.30) (2022-08-17)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **ui:** run eslint --fix ([#1542](https://github.com/parca-dev/parca/issues/1542)) ([e522131](https://github.com/parca-dev/parca/commit/e5221318fc1140d661c45d2d04b096bfebba4af4))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## [0.14.29](https://github.com/parca-dev/parca/compare/ui-v0.14.28...ui-v0.14.29) (2022-08-15)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## 0.14.21 (2022-08-10)
|
|
33
|
+
|
|
34
|
+
**Note:** Version bump only for package @parca/profile
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
6
40
|
## [0.14.16](https://github.com/parca-dev/parca/compare/ui-v0.14.15...ui-v0.14.16) (2022-08-03)
|
|
7
41
|
|
|
8
42
|
**Note:** Version bump only for package @parca/profile
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.31",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@iconify/react": "^3.2.2",
|
|
7
7
|
"@parca/client": "^0.14.16",
|
|
8
|
-
"@parca/dynamicsize": "^0.14.
|
|
9
|
-
"@parca/parser": "^0.14.
|
|
8
|
+
"@parca/dynamicsize": "^0.14.29",
|
|
9
|
+
"@parca/parser": "^0.14.29",
|
|
10
10
|
"d3-scale": "^4.0.2",
|
|
11
11
|
"d3-selection": "3.0.0",
|
|
12
12
|
"react-copy-to-clipboard": "^5.1.0"
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"access": "public",
|
|
23
23
|
"registry": "https://registry.npmjs.org/"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "ad5f13b18fb7c5dd70df3dc6b40477e44f839381"
|
|
26
26
|
}
|
package/src/IcicleGraph.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import React, {MouseEvent, useEffect, useRef, useState} from 'react';
|
|
2
15
|
|
|
3
16
|
import {throttle} from 'lodash';
|
|
@@ -98,7 +111,11 @@ function IcicleRect({
|
|
|
98
111
|
height={height - 1}
|
|
99
112
|
style={{
|
|
100
113
|
opacity:
|
|
101
|
-
|
|
114
|
+
currentSearchString !== undefined &&
|
|
115
|
+
currentSearchString !== '' &&
|
|
116
|
+
!isSearchMatch(currentSearchString, name)
|
|
117
|
+
? 0.5
|
|
118
|
+
: 1,
|
|
102
119
|
fill: color,
|
|
103
120
|
}}
|
|
104
121
|
/>
|
|
@@ -117,7 +134,7 @@ export function nodeLabel(node: FlamegraphNode): string {
|
|
|
117
134
|
if (node.meta === undefined) return '<unknown>';
|
|
118
135
|
const mapping = `${
|
|
119
136
|
node.meta?.mapping?.file !== undefined && node.meta?.mapping?.file !== ''
|
|
120
|
-
? '[' + getLastItem(node.meta.mapping.file) + '] '
|
|
137
|
+
? '[' + (getLastItem(node.meta.mapping.file) ?? '') + '] '
|
|
121
138
|
: ''
|
|
122
139
|
}`;
|
|
123
140
|
if (node.meta.function?.name !== undefined && node.meta.function?.name !== '')
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {Flamegraph} from '@parca/client';
|
|
2
15
|
import {useAppSelector, selectCompareMode} from '@parca/store';
|
|
3
16
|
import {useContainerDimensions} from '@parca/dynamicsize';
|
package/src/ProfileSource.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import React from 'react';
|
|
2
15
|
import {formatDate} from '@parca/functions';
|
|
3
16
|
import {Query, ProfileType} from '@parca/parser';
|
package/src/ProfileView.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import React, {useEffect, useMemo, useState} from 'react';
|
|
2
15
|
|
|
3
16
|
import {parseParams} from '@parca/functions';
|
|
@@ -57,7 +70,7 @@ export const useProfileVisState = (): ProfileVisState => {
|
|
|
57
70
|
const router = parseParams(window.location.search);
|
|
58
71
|
const currentViewFromURL = router.currentProfileView as string;
|
|
59
72
|
const [currentView, setCurrentView] = useState<VisualizationType>(
|
|
60
|
-
(currentViewFromURL as VisualizationType)
|
|
73
|
+
(currentViewFromURL as VisualizationType) ?? 'icicle'
|
|
61
74
|
);
|
|
62
75
|
|
|
63
76
|
return {currentView, setCurrentView};
|
|
@@ -85,13 +98,13 @@ export const ProfileView = ({
|
|
|
85
98
|
|
|
86
99
|
const isLoading = useMemo(() => {
|
|
87
100
|
if (currentView === 'icicle') {
|
|
88
|
-
return
|
|
101
|
+
return Boolean(flamegraphData?.loading);
|
|
89
102
|
}
|
|
90
103
|
if (currentView === 'table') {
|
|
91
|
-
return
|
|
104
|
+
return Boolean(topTableData?.loading);
|
|
92
105
|
}
|
|
93
106
|
if (currentView === 'both') {
|
|
94
|
-
return
|
|
107
|
+
return Boolean(flamegraphData?.loading) || Boolean(topTableData?.loading);
|
|
95
108
|
}
|
|
96
109
|
return false;
|
|
97
110
|
}, [currentView, flamegraphData?.loading, topTableData?.loading]);
|
|
@@ -113,7 +126,7 @@ export const ProfileView = ({
|
|
|
113
126
|
|
|
114
127
|
const downloadPProf = async (e: React.MouseEvent<HTMLElement>) => {
|
|
115
128
|
e.preventDefault();
|
|
116
|
-
if (
|
|
129
|
+
if (profileSource == null || queryClient == null) {
|
|
117
130
|
return;
|
|
118
131
|
}
|
|
119
132
|
|
|
@@ -156,14 +169,14 @@ export const ProfileView = ({
|
|
|
156
169
|
<div className="flex py-3 w-full">
|
|
157
170
|
<div className="w-2/5 flex space-x-4">
|
|
158
171
|
<div className="flex space-x-1">
|
|
159
|
-
{profileSource && queryClient ? (
|
|
172
|
+
{profileSource != null && queryClient != null ? (
|
|
160
173
|
<ProfileShareButton
|
|
161
174
|
queryRequest={profileSource.QueryRequest()}
|
|
162
175
|
queryClient={queryClient}
|
|
163
176
|
/>
|
|
164
177
|
) : null}
|
|
165
178
|
|
|
166
|
-
<Button color="neutral" onClick={downloadPProf}>
|
|
179
|
+
<Button color="neutral" onClick={void downloadPProf}>
|
|
167
180
|
Download pprof
|
|
168
181
|
</Button>
|
|
169
182
|
</div>
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {QueryServiceClient, QueryRequest_ReportType} from '@parca/client';
|
|
2
15
|
|
|
3
16
|
import {useQuery} from './useQuery';
|
|
@@ -25,7 +38,7 @@ export const ProfileViewWithData = ({
|
|
|
25
38
|
response: flamegraphResponse,
|
|
26
39
|
error: flamegraphError,
|
|
27
40
|
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_UNSPECIFIED, {
|
|
28
|
-
skip: currentView
|
|
41
|
+
skip: currentView !== 'icicle' && currentView !== 'both',
|
|
29
42
|
});
|
|
30
43
|
|
|
31
44
|
const {
|
|
@@ -33,7 +46,7 @@ export const ProfileViewWithData = ({
|
|
|
33
46
|
response: topTableResponse,
|
|
34
47
|
error: topTableError,
|
|
35
48
|
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.TOP, {
|
|
36
|
-
skip: currentView
|
|
49
|
+
skip: currentView !== 'table' && currentView !== 'both',
|
|
37
50
|
});
|
|
38
51
|
|
|
39
52
|
const sampleUnit = profileSource.ProfileType().sampleUnit;
|
package/src/TopTable.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import React from 'react';
|
|
2
15
|
|
|
3
16
|
import {getLastItem, valueFormatter, isSearchMatch} from '@parca/functions';
|
|
@@ -33,7 +46,7 @@ const useSortableData = (top?: Top, config = {key: 'cumulative', direction: 'des
|
|
|
33
46
|
config
|
|
34
47
|
);
|
|
35
48
|
|
|
36
|
-
const rawTableReport = top ? top.list : [];
|
|
49
|
+
const rawTableReport = top != null ? top.list : [];
|
|
37
50
|
|
|
38
51
|
const items = rawTableReport.map(node => ({
|
|
39
52
|
...node,
|
|
@@ -44,9 +57,9 @@ const useSortableData = (top?: Top, config = {key: 'cumulative', direction: 'des
|
|
|
44
57
|
}));
|
|
45
58
|
|
|
46
59
|
const sortedItems = React.useMemo(() => {
|
|
47
|
-
if (
|
|
60
|
+
if (items.length === 0) return;
|
|
48
61
|
|
|
49
|
-
|
|
62
|
+
const sortableItems = [...items];
|
|
50
63
|
if (sortConfig !== null) {
|
|
51
64
|
sortableItems.sort((a, b) => {
|
|
52
65
|
if (a[sortConfig.key] < b[sortConfig.key]) {
|
|
@@ -61,9 +74,9 @@ const useSortableData = (top?: Top, config = {key: 'cumulative', direction: 'des
|
|
|
61
74
|
return sortableItems;
|
|
62
75
|
}, [items, sortConfig]);
|
|
63
76
|
|
|
64
|
-
const requestSort = key => {
|
|
77
|
+
const requestSort = (key: string) => {
|
|
65
78
|
let direction = 'desc';
|
|
66
|
-
if (sortConfig && sortConfig.key === key && sortConfig.direction === 'desc') {
|
|
79
|
+
if (sortConfig != null && sortConfig.key === key && sortConfig.direction === 'desc') {
|
|
67
80
|
direction = 'asc';
|
|
68
81
|
}
|
|
69
82
|
setSortConfig({key, direction});
|
|
@@ -76,14 +89,14 @@ export const RowLabel = (meta: TopNodeMeta | undefined): string => {
|
|
|
76
89
|
if (meta === undefined) return '<unknown>';
|
|
77
90
|
const mapping = `${
|
|
78
91
|
meta?.mapping?.file !== undefined && meta?.mapping?.file !== ''
|
|
79
|
-
? `[${getLastItem(meta.mapping.file)}]`
|
|
92
|
+
? `[${getLastItem(meta.mapping.file) ?? ''}]`
|
|
80
93
|
: ''
|
|
81
94
|
}`;
|
|
82
95
|
if (meta.function?.name !== undefined && meta.function?.name !== '')
|
|
83
96
|
return `${mapping} ${meta.function.name}`;
|
|
84
97
|
|
|
85
98
|
const address = hexifyAddress(meta.location?.address);
|
|
86
|
-
const fallback = `${mapping} ${address
|
|
99
|
+
const fallback = `${mapping} ${address}`;
|
|
87
100
|
|
|
88
101
|
return fallback === '' ? '<unknown>' : fallback;
|
|
89
102
|
};
|
|
@@ -96,11 +109,11 @@ export const TopTable = ({data: top, sampleUnit}: TopTableProps): JSX.Element =>
|
|
|
96
109
|
|
|
97
110
|
const unit = sampleUnit;
|
|
98
111
|
|
|
99
|
-
const total = top ? top.list.length : 0;
|
|
112
|
+
const total = top != null ? top.list.length : 0;
|
|
100
113
|
if (total === 0) return <>Profile has no samples</>;
|
|
101
114
|
|
|
102
|
-
const getClassNamesFor = name => {
|
|
103
|
-
if (
|
|
115
|
+
const getClassNamesFor = (name: string) => {
|
|
116
|
+
if (sortConfig == null) {
|
|
104
117
|
return;
|
|
105
118
|
}
|
|
106
119
|
return sortConfig.key === name ? sortConfig.direction : undefined;
|
|
@@ -125,7 +138,9 @@ export const TopTable = ({data: top, sampleUnit}: TopTableProps): JSX.Element =>
|
|
|
125
138
|
onClick={() => requestSort('name')}
|
|
126
139
|
>
|
|
127
140
|
Name
|
|
128
|
-
<span
|
|
141
|
+
<span
|
|
142
|
+
className={`inline-block align-middle ml-2 ${getClassNamesFor('name') ?? ''}`}
|
|
143
|
+
>
|
|
129
144
|
<Arrow direction={getClassNamesFor('name')} />
|
|
130
145
|
</span>
|
|
131
146
|
</th>
|
|
@@ -134,7 +149,9 @@ export const TopTable = ({data: top, sampleUnit}: TopTableProps): JSX.Element =>
|
|
|
134
149
|
onClick={() => requestSort('flat')}
|
|
135
150
|
>
|
|
136
151
|
Flat
|
|
137
|
-
<span
|
|
152
|
+
<span
|
|
153
|
+
className={`inline-block align-middle ml-2 ${getClassNamesFor('flat') ?? ''}`}
|
|
154
|
+
>
|
|
138
155
|
<Arrow direction={getClassNamesFor('flat')} />
|
|
139
156
|
</span>
|
|
140
157
|
</th>
|
|
@@ -144,7 +161,9 @@ export const TopTable = ({data: top, sampleUnit}: TopTableProps): JSX.Element =>
|
|
|
144
161
|
>
|
|
145
162
|
Cumulative
|
|
146
163
|
<span
|
|
147
|
-
className={`inline-block align-middle ml-2 ${
|
|
164
|
+
className={`inline-block align-middle ml-2 ${
|
|
165
|
+
getClassNamesFor('cumulative') ?? ''
|
|
166
|
+
}`}
|
|
148
167
|
>
|
|
149
168
|
<Arrow direction={getClassNamesFor('cumulative')} />
|
|
150
169
|
</span>
|
|
@@ -155,7 +174,9 @@ export const TopTable = ({data: top, sampleUnit}: TopTableProps): JSX.Element =>
|
|
|
155
174
|
onClick={() => requestSort('diff')}
|
|
156
175
|
>
|
|
157
176
|
Diff
|
|
158
|
-
<span
|
|
177
|
+
<span
|
|
178
|
+
className={`inline-block align-middle ml-2 ${getClassNamesFor('diff') ?? ''}`}
|
|
179
|
+
>
|
|
159
180
|
<Arrow direction={getClassNamesFor('diff')} />
|
|
160
181
|
</span>
|
|
161
182
|
</th>
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {SuffixParams, ParseLabels} from '../ProfileSource';
|
|
2
15
|
|
|
3
16
|
test('prefixes keys', () => {
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {Fragment, useState} from 'react';
|
|
2
15
|
import {Popover, Transition} from '@headlessui/react';
|
|
3
16
|
import {useAppSelector, selectDarkMode} from '@parca/store';
|
|
@@ -44,9 +57,9 @@ const DiffLegendBar = ({
|
|
|
44
57
|
const DiffLegend = () => {
|
|
45
58
|
const [showLegendTooltip, setShowLegendTooltip] = useState(false);
|
|
46
59
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
47
|
-
|
|
60
|
+
const [referenceElement, setReferenceElement] = useState<HTMLDivElement | null>(null);
|
|
48
61
|
|
|
49
|
-
const {styles, attributes
|
|
62
|
+
const {styles, attributes} = usePopper(referenceElement, popperElement, {
|
|
50
63
|
placement: 'auto-start',
|
|
51
64
|
strategy: 'absolute',
|
|
52
65
|
});
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {useState} from 'react';
|
|
2
15
|
import cx from 'classnames';
|
|
3
16
|
import {Icon} from '@iconify/react';
|
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {useState} from 'react';
|
|
2
15
|
import {Button, Modal, useGrpcMetadata} from '@parca/components';
|
|
3
16
|
import {Icon} from '@iconify/react';
|
|
@@ -30,7 +43,7 @@ const ProfileShareModal = ({
|
|
|
30
43
|
const metadata = useGrpcMetadata();
|
|
31
44
|
const isFormDataValid = () => true;
|
|
32
45
|
|
|
33
|
-
const handleSubmit: () => void = async () => {
|
|
46
|
+
const handleSubmit: () => Promise<void> = async () => {
|
|
34
47
|
try {
|
|
35
48
|
setLoading(true);
|
|
36
49
|
const {response} = await queryClient.shareProfile(
|
|
@@ -76,7 +89,7 @@ const ProfileShareModal = ({
|
|
|
76
89
|
className="w-fit mt-4"
|
|
77
90
|
onClick={e => {
|
|
78
91
|
e.preventDefault();
|
|
79
|
-
handleSubmit();
|
|
92
|
+
void handleSubmit();
|
|
80
93
|
}}
|
|
81
94
|
disabled={loading || !isFormDataValid()}
|
|
82
95
|
type="submit"
|
package/src/index.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
export * from './IcicleGraph';
|
|
2
15
|
export * from './ProfileIcicleGraph';
|
|
3
16
|
export * from './ProfileSource';
|
package/src/useDelayedLoader.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {useEffect, useState} from 'react';
|
|
2
15
|
|
|
3
16
|
interface DelayedLoaderOptions {
|
|
@@ -5,10 +18,10 @@ interface DelayedLoaderOptions {
|
|
|
5
18
|
}
|
|
6
19
|
|
|
7
20
|
const useDelayedLoader = (isLoading = false, options?: DelayedLoaderOptions) => {
|
|
8
|
-
const {delay = 500} = options
|
|
21
|
+
const {delay = 500} = options ?? {};
|
|
9
22
|
const [isLoaderVisible, setIsLoaderVisible] = useState<boolean>(false);
|
|
10
23
|
useEffect(() => {
|
|
11
|
-
let showLoaderTimeout
|
|
24
|
+
let showLoaderTimeout: ReturnType<typeof setTimeout>;
|
|
12
25
|
if (isLoading && !isLoaderVisible) {
|
|
13
26
|
// if the request takes longer than half a second, show the loading icon
|
|
14
27
|
showLoaderTimeout = setTimeout(() => {
|
|
@@ -18,7 +31,7 @@ const useDelayedLoader = (isLoading = false, options?: DelayedLoaderOptions) =>
|
|
|
18
31
|
setIsLoaderVisible(false);
|
|
19
32
|
}
|
|
20
33
|
return () => clearTimeout(showLoaderTimeout);
|
|
21
|
-
}, [isLoading]);
|
|
34
|
+
}, [isLoading, isLoaderVisible, delay]);
|
|
22
35
|
|
|
23
36
|
return isLoaderVisible;
|
|
24
37
|
};
|
package/src/useQuery.tsx
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {useEffect, useState} from 'react';
|
|
2
15
|
|
|
3
16
|
import {QueryServiceClient, QueryResponse, QueryRequest_ReportType} from '@parca/client';
|
|
@@ -22,7 +35,7 @@ export const useQuery = (
|
|
|
22
35
|
reportType: QueryRequest_ReportType,
|
|
23
36
|
options?: UseQueryOptions
|
|
24
37
|
): IQueryResult => {
|
|
25
|
-
const {skip = false} = options
|
|
38
|
+
const {skip = false} = options ?? {};
|
|
26
39
|
const [result, setResult] = useState<IQueryResult>({
|
|
27
40
|
response: null,
|
|
28
41
|
error: null,
|
|
@@ -45,9 +58,9 @@ export const useQuery = (
|
|
|
45
58
|
const call = client.query(req, {meta: metadata});
|
|
46
59
|
|
|
47
60
|
call.response
|
|
48
|
-
.then(response => setResult({response
|
|
49
|
-
.catch(error => setResult({error
|
|
50
|
-
}, [client, profileSource, metadata, reportType]);
|
|
61
|
+
.then(response => setResult({response, error: null, isLoading: false}))
|
|
62
|
+
.catch(error => setResult({error, response: null, isLoading: false}));
|
|
63
|
+
}, [skip, client, profileSource, metadata, reportType]);
|
|
51
64
|
|
|
52
65
|
return result;
|
|
53
66
|
};
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
import {QueryRequest, QueryRequest_ReportType, QueryServiceClient} from '@parca/client';
|
|
2
15
|
import {RpcMetadata} from '@protobuf-ts/runtime-rpc';
|
|
3
16
|
|