@parca/profile 0.16.227 → 0.16.229
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/GraphTooltipArrow/Content.d.ts +3 -1
- package/dist/GraphTooltipArrow/Content.js +44 -6
- package/dist/GraphTooltipArrow/ExpandOnHoverValue.js +1 -1
- package/dist/MetricsGraph/useMetricsGraphDimensions.js +9 -0
- package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +1 -1
- package/dist/ProfileView/ProfileViewContext.d.ts +14 -0
- package/dist/ProfileView/ProfileViewContext.js +30 -0
- package/dist/ProfileView/ViewSelector.js +1 -0
- package/dist/ProfileView/index.d.ts +11 -4
- package/dist/ProfileView/index.js +21 -12
- package/dist/ProfileViewWithData.js +35 -11
- package/dist/SourceView/Highlighter.d.ts +16 -0
- package/dist/SourceView/Highlighter.js +80 -0
- package/dist/SourceView/LineNo.d.ts +6 -0
- package/dist/SourceView/LineNo.js +23 -0
- package/dist/SourceView/index.d.ts +11 -0
- package/dist/SourceView/index.js +37 -0
- package/dist/Table/index.d.ts +14 -0
- package/dist/Table/index.js +184 -0
- package/dist/styles.css +1 -1
- package/dist/useQuery.d.ts +3 -0
- package/dist/useQuery.js +17 -1
- package/package.json +10 -8
- package/src/GraphTooltipArrow/Content.tsx +88 -9
- package/src/GraphTooltipArrow/ExpandOnHoverValue.tsx +1 -1
- package/src/MetricsGraph/useMetricsGraphDimensions.ts +9 -0
- package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +1 -0
- package/src/ProfileView/ProfileViewContext.tsx +52 -0
- package/src/ProfileView/ViewSelector.tsx +1 -0
- package/src/ProfileView/index.tsx +136 -99
- package/src/ProfileViewWithData.tsx +48 -15
- package/src/SourceView/Highlighter.tsx +196 -0
- package/src/SourceView/LineNo.tsx +31 -0
- package/src/SourceView/index.tsx +74 -0
- package/src/Table/index.tsx +285 -0
- package/src/useQuery.tsx +20 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Copyright 2022 The Parca Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
|
|
14
|
+
import {ReactNode, createContext, useContext} from 'react';
|
|
15
|
+
|
|
16
|
+
import {ProfileSource} from '../ProfileSource';
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
profileSource?: ProfileSource;
|
|
20
|
+
sampleUnit: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const defaultValue: Props = {
|
|
24
|
+
profileSource: undefined,
|
|
25
|
+
sampleUnit: 'bytes',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const ProfileViewContext = createContext<Props>(defaultValue);
|
|
29
|
+
|
|
30
|
+
export const ProfileViewContextProvider = ({
|
|
31
|
+
children,
|
|
32
|
+
value,
|
|
33
|
+
}: {
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
value?: Props;
|
|
36
|
+
}): JSX.Element => {
|
|
37
|
+
return (
|
|
38
|
+
<ProfileViewContext.Provider value={{...defaultValue, ...(value ?? {})}}>
|
|
39
|
+
{children}
|
|
40
|
+
</ProfileViewContext.Provider>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const useProfileViewContext = (): Props => {
|
|
45
|
+
const context = useContext(ProfileViewContext);
|
|
46
|
+
if (context == null) {
|
|
47
|
+
return defaultValue;
|
|
48
|
+
}
|
|
49
|
+
return context;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default ProfileViewContext;
|
|
@@ -43,6 +43,7 @@ const ViewSelector = ({
|
|
|
43
43
|
const allItems: Array<{key: string; canBeSelected: boolean; supportingText?: string}> = [
|
|
44
44
|
{key: 'table', canBeSelected: !dashboardItems.includes('table')},
|
|
45
45
|
{key: 'icicle', canBeSelected: !dashboardItems.includes('icicle')},
|
|
46
|
+
{key: 'source', canBeSelected: false},
|
|
46
47
|
];
|
|
47
48
|
if (callgraphEnabled) {
|
|
48
49
|
allItems.push({
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {Profiler, ProfilerProps, useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
|
-
import {Table} from 'apache-arrow';
|
|
16
|
+
import {Table as ArrowTable} from 'apache-arrow';
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
import {scaleLinear} from 'd3';
|
|
19
19
|
import graphviz from 'graphviz-wasm';
|
|
@@ -25,7 +25,14 @@ import {
|
|
|
25
25
|
type DropResult,
|
|
26
26
|
} from 'react-beautiful-dnd';
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
Callgraph as CallgraphType,
|
|
30
|
+
Flamegraph,
|
|
31
|
+
QueryServiceClient,
|
|
32
|
+
Source,
|
|
33
|
+
TableArrow,
|
|
34
|
+
Top,
|
|
35
|
+
} from '@parca/client';
|
|
29
36
|
import {
|
|
30
37
|
Button,
|
|
31
38
|
Card,
|
|
@@ -42,10 +49,12 @@ import {Callgraph} from '../';
|
|
|
42
49
|
import {jsonToDot} from '../Callgraph/utils';
|
|
43
50
|
import ProfileIcicleGraph from '../ProfileIcicleGraph';
|
|
44
51
|
import {ProfileSource} from '../ProfileSource';
|
|
45
|
-
import {
|
|
52
|
+
import {SourceView} from '../SourceView';
|
|
53
|
+
import Table from '../Table';
|
|
46
54
|
import ProfileShareButton from '../components/ProfileShareButton';
|
|
47
55
|
import useDelayedLoader from '../useDelayedLoader';
|
|
48
56
|
import FilterByFunctionButton from './FilterByFunctionButton';
|
|
57
|
+
import {ProfileViewContextProvider} from './ProfileViewContext';
|
|
49
58
|
import ViewSelector from './ViewSelector';
|
|
50
59
|
import {VisualizationPanel} from './VisualizationPanel';
|
|
51
60
|
|
|
@@ -54,7 +63,7 @@ type NavigateFunction = (path: string, queryParams: any, options?: {replace?: bo
|
|
|
54
63
|
export interface FlamegraphData {
|
|
55
64
|
loading: boolean;
|
|
56
65
|
data?: Flamegraph;
|
|
57
|
-
table?:
|
|
66
|
+
table?: ArrowTable<any>;
|
|
58
67
|
total?: bigint;
|
|
59
68
|
filtered?: bigint;
|
|
60
69
|
error?: any;
|
|
@@ -62,7 +71,8 @@ export interface FlamegraphData {
|
|
|
62
71
|
|
|
63
72
|
export interface TopTableData {
|
|
64
73
|
loading: boolean;
|
|
65
|
-
|
|
74
|
+
arrow?: TableArrow;
|
|
75
|
+
data?: Top; // TODO: Remove this once we only have arrow support
|
|
66
76
|
total?: bigint;
|
|
67
77
|
filtered?: bigint;
|
|
68
78
|
error?: any;
|
|
@@ -76,12 +86,19 @@ interface CallgraphData {
|
|
|
76
86
|
error?: any;
|
|
77
87
|
}
|
|
78
88
|
|
|
89
|
+
interface SourceData {
|
|
90
|
+
loading: boolean;
|
|
91
|
+
data?: Source;
|
|
92
|
+
error?: any;
|
|
93
|
+
}
|
|
94
|
+
|
|
79
95
|
export interface ProfileViewProps {
|
|
80
96
|
total: bigint;
|
|
81
97
|
filtered: bigint;
|
|
82
98
|
flamegraphData?: FlamegraphData;
|
|
83
99
|
topTableData?: TopTableData;
|
|
84
100
|
callgraphData?: CallgraphData;
|
|
101
|
+
sourceData?: SourceData;
|
|
85
102
|
sampleUnit: string;
|
|
86
103
|
profileSource?: ProfileSource;
|
|
87
104
|
queryClient?: QueryServiceClient;
|
|
@@ -106,6 +123,7 @@ export const ProfileView = ({
|
|
|
106
123
|
flamegraphData,
|
|
107
124
|
topTableData,
|
|
108
125
|
callgraphData,
|
|
126
|
+
sourceData,
|
|
109
127
|
sampleUnit,
|
|
110
128
|
profileSource,
|
|
111
129
|
queryClient,
|
|
@@ -158,12 +176,16 @@ export const ProfileView = ({
|
|
|
158
176
|
if (dashboardItems.includes('table')) {
|
|
159
177
|
return Boolean(topTableData?.loading);
|
|
160
178
|
}
|
|
179
|
+
if (dashboardItems.includes('source')) {
|
|
180
|
+
return Boolean(sourceData?.loading);
|
|
181
|
+
}
|
|
161
182
|
return false;
|
|
162
183
|
}, [
|
|
163
184
|
dashboardItems,
|
|
164
185
|
callgraphData?.loading,
|
|
165
186
|
flamegraphData?.loading,
|
|
166
187
|
topTableData?.loading,
|
|
188
|
+
sourceData?.loading,
|
|
167
189
|
callgraphSVG,
|
|
168
190
|
]);
|
|
169
191
|
|
|
@@ -274,9 +296,9 @@ export const ProfileView = ({
|
|
|
274
296
|
}
|
|
275
297
|
case 'table': {
|
|
276
298
|
return topTableData != null ? (
|
|
277
|
-
<
|
|
299
|
+
<Table
|
|
278
300
|
loading={topTableData.loading}
|
|
279
|
-
data={topTableData.
|
|
301
|
+
data={topTableData.arrow?.record}
|
|
280
302
|
sampleUnit={sampleUnit}
|
|
281
303
|
navigateTo={navigateTo}
|
|
282
304
|
setActionButtons={setActionButtons}
|
|
@@ -286,6 +308,19 @@ export const ProfileView = ({
|
|
|
286
308
|
<></>
|
|
287
309
|
);
|
|
288
310
|
}
|
|
311
|
+
case 'source': {
|
|
312
|
+
return sourceData != null ? (
|
|
313
|
+
<SourceView
|
|
314
|
+
loading={sourceData.loading}
|
|
315
|
+
data={sourceData.data}
|
|
316
|
+
total={total}
|
|
317
|
+
filtered={filtered}
|
|
318
|
+
setActionButtons={setActionButtons}
|
|
319
|
+
/>
|
|
320
|
+
) : (
|
|
321
|
+
<></>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
289
324
|
default: {
|
|
290
325
|
return <></>;
|
|
291
326
|
}
|
|
@@ -314,102 +349,104 @@ export const ProfileView = ({
|
|
|
314
349
|
|
|
315
350
|
return (
|
|
316
351
|
<KeyDownProvider>
|
|
317
|
-
<
|
|
318
|
-
<
|
|
319
|
-
<Card
|
|
320
|
-
<
|
|
321
|
-
<div className="flex
|
|
322
|
-
<div className="flex space-x-1">
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
e
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
352
|
+
<ProfileViewContextProvider value={{profileSource, sampleUnit}}>
|
|
353
|
+
<div className="py-3">
|
|
354
|
+
<Card>
|
|
355
|
+
<Card.Body>
|
|
356
|
+
<div className="flex w-full py-3">
|
|
357
|
+
<div className="flex space-x-4 lg:w-1/2">
|
|
358
|
+
<div className="flex space-x-1">
|
|
359
|
+
{profileSource !== undefined && queryClient !== undefined ? (
|
|
360
|
+
<ProfileShareButton
|
|
361
|
+
queryRequest={profileSource.QueryRequest()}
|
|
362
|
+
queryClient={queryClient}
|
|
363
|
+
/>
|
|
364
|
+
) : null}
|
|
365
|
+
|
|
366
|
+
<Button
|
|
367
|
+
color="neutral"
|
|
368
|
+
onClick={e => {
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
onDownloadPProf();
|
|
371
|
+
}}
|
|
372
|
+
disabled={pprofDownloading}
|
|
373
|
+
>
|
|
374
|
+
{pprofDownloading != null && pprofDownloading
|
|
375
|
+
? 'Downloading'
|
|
376
|
+
: 'Download pprof'}
|
|
377
|
+
</Button>
|
|
378
|
+
</div>
|
|
379
|
+
<FilterByFunctionButton navigateTo={navigateTo} />
|
|
380
|
+
</div>
|
|
381
|
+
|
|
382
|
+
<div className="ml-auto flex gap-2">
|
|
383
|
+
<ViewSelector
|
|
384
|
+
defaultValue=""
|
|
385
|
+
navigateTo={navigateTo}
|
|
386
|
+
position={-1}
|
|
387
|
+
placeholderText="Add panel..."
|
|
388
|
+
primary
|
|
389
|
+
addView={true}
|
|
390
|
+
disabled={isMultiPanelView || dashboardItems.length < 1}
|
|
391
|
+
/>
|
|
342
392
|
</div>
|
|
343
|
-
<FilterByFunctionButton navigateTo={navigateTo} />
|
|
344
393
|
</div>
|
|
345
394
|
|
|
346
|
-
<div className="
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
395
|
+
<div className="w-full" ref={ref}>
|
|
396
|
+
{isLoaderVisible ? (
|
|
397
|
+
<>{loader}</>
|
|
398
|
+
) : (
|
|
399
|
+
<DragDropContext onDragEnd={onDragEnd}>
|
|
400
|
+
<Droppable droppableId="droppable" direction="horizontal">
|
|
401
|
+
{provided => (
|
|
402
|
+
<div
|
|
403
|
+
ref={provided.innerRef}
|
|
404
|
+
className="flex w-full justify-between space-x-4"
|
|
405
|
+
{...provided.droppableProps}
|
|
406
|
+
>
|
|
407
|
+
{dashboardItems.map((dashboardItem, index) => {
|
|
408
|
+
return (
|
|
409
|
+
<Draggable
|
|
410
|
+
key={dashboardItem}
|
|
411
|
+
draggableId={dashboardItem}
|
|
412
|
+
index={index}
|
|
413
|
+
isDragDisabled={!isMultiPanelView}
|
|
414
|
+
>
|
|
415
|
+
{(provided, snapshot: {isDragging: boolean}) => (
|
|
416
|
+
<div
|
|
417
|
+
ref={provided.innerRef}
|
|
418
|
+
{...provided.draggableProps}
|
|
419
|
+
key={dashboardItem}
|
|
420
|
+
className={cx(
|
|
421
|
+
'rounded border border-gray-300 p-3 dark:border-gray-500 dark:bg-gray-700',
|
|
422
|
+
isMultiPanelView ? 'w-1/2' : 'w-full',
|
|
423
|
+
snapshot.isDragging ? 'bg-gray-200' : 'bg-white'
|
|
424
|
+
)}
|
|
425
|
+
>
|
|
426
|
+
<VisualizationPanel
|
|
427
|
+
handleClosePanel={handleClosePanel}
|
|
428
|
+
isMultiPanelView={isMultiPanelView}
|
|
429
|
+
dashboardItem={dashboardItem}
|
|
430
|
+
getDashboardItemByType={getDashboardItemByType}
|
|
431
|
+
dragHandleProps={provided.dragHandleProps}
|
|
432
|
+
navigateTo={navigateTo}
|
|
433
|
+
index={index}
|
|
434
|
+
/>
|
|
435
|
+
</div>
|
|
436
|
+
)}
|
|
437
|
+
</Draggable>
|
|
438
|
+
);
|
|
439
|
+
})}
|
|
440
|
+
</div>
|
|
441
|
+
)}
|
|
442
|
+
</Droppable>
|
|
443
|
+
</DragDropContext>
|
|
444
|
+
)}
|
|
356
445
|
</div>
|
|
357
|
-
</
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
<>{loader}</>
|
|
362
|
-
) : (
|
|
363
|
-
<DragDropContext onDragEnd={onDragEnd}>
|
|
364
|
-
<Droppable droppableId="droppable" direction="horizontal">
|
|
365
|
-
{provided => (
|
|
366
|
-
<div
|
|
367
|
-
ref={provided.innerRef}
|
|
368
|
-
className="flex w-full justify-between space-x-4"
|
|
369
|
-
{...provided.droppableProps}
|
|
370
|
-
>
|
|
371
|
-
{dashboardItems.map((dashboardItem, index) => {
|
|
372
|
-
return (
|
|
373
|
-
<Draggable
|
|
374
|
-
key={dashboardItem}
|
|
375
|
-
draggableId={dashboardItem}
|
|
376
|
-
index={index}
|
|
377
|
-
isDragDisabled={!isMultiPanelView}
|
|
378
|
-
>
|
|
379
|
-
{(provided, snapshot: {isDragging: boolean}) => (
|
|
380
|
-
<div
|
|
381
|
-
ref={provided.innerRef}
|
|
382
|
-
{...provided.draggableProps}
|
|
383
|
-
key={dashboardItem}
|
|
384
|
-
className={cx(
|
|
385
|
-
'rounded border border-gray-300 p-3 dark:border-gray-500 dark:bg-gray-700',
|
|
386
|
-
isMultiPanelView ? 'w-1/2' : 'w-full',
|
|
387
|
-
snapshot.isDragging ? 'bg-gray-200' : 'bg-white'
|
|
388
|
-
)}
|
|
389
|
-
>
|
|
390
|
-
<VisualizationPanel
|
|
391
|
-
handleClosePanel={handleClosePanel}
|
|
392
|
-
isMultiPanelView={isMultiPanelView}
|
|
393
|
-
dashboardItem={dashboardItem}
|
|
394
|
-
getDashboardItemByType={getDashboardItemByType}
|
|
395
|
-
dragHandleProps={provided.dragHandleProps}
|
|
396
|
-
navigateTo={navigateTo}
|
|
397
|
-
index={index}
|
|
398
|
-
/>
|
|
399
|
-
</div>
|
|
400
|
-
)}
|
|
401
|
-
</Draggable>
|
|
402
|
-
);
|
|
403
|
-
})}
|
|
404
|
-
</div>
|
|
405
|
-
)}
|
|
406
|
-
</Droppable>
|
|
407
|
-
</DragDropContext>
|
|
408
|
-
)}
|
|
409
|
-
</div>
|
|
410
|
-
</Card.Body>
|
|
411
|
-
</Card>
|
|
412
|
-
</div>
|
|
446
|
+
</Card.Body>
|
|
447
|
+
</Card>
|
|
448
|
+
</div>
|
|
449
|
+
</ProfileViewContextProvider>
|
|
413
450
|
</KeyDownProvider>
|
|
414
451
|
);
|
|
415
452
|
};
|
|
@@ -40,6 +40,10 @@ export const ProfileViewWithData = ({
|
|
|
40
40
|
}: ProfileViewWithDataProps): JSX.Element => {
|
|
41
41
|
const metadata = useGrpcMetadata();
|
|
42
42
|
const [dashboardItems = ['icicle']] = useURLState({param: 'dashboard_items', navigateTo});
|
|
43
|
+
const [sourceBuildID] = useURLState({param: 'source_buildid', navigateTo}) as unknown as [string];
|
|
44
|
+
const [sourceFilename] = useURLState({param: 'source_filename', navigateTo}) as unknown as [
|
|
45
|
+
string
|
|
46
|
+
];
|
|
43
47
|
const [groupBy = [FIELD_FUNCTION_NAME]] = useURLState({param: 'group_by', navigateTo});
|
|
44
48
|
|
|
45
49
|
const [enableTrimming] = useUserPreference<boolean>(USER_PREFERENCES.ENABLE_GRAPH_TRIMMING.key);
|
|
@@ -78,10 +82,10 @@ export const ProfileViewWithData = ({
|
|
|
78
82
|
const {perf} = useParcaContext();
|
|
79
83
|
|
|
80
84
|
const {
|
|
81
|
-
isLoading:
|
|
82
|
-
response:
|
|
83
|
-
error:
|
|
84
|
-
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.
|
|
85
|
+
isLoading: tableLoading,
|
|
86
|
+
response: tableResponse,
|
|
87
|
+
error: tableError,
|
|
88
|
+
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.TABLE_ARROW, {
|
|
85
89
|
skip: !dashboardItems.includes('table'),
|
|
86
90
|
});
|
|
87
91
|
|
|
@@ -93,6 +97,16 @@ export const ProfileViewWithData = ({
|
|
|
93
97
|
skip: !dashboardItems.includes('callgraph'),
|
|
94
98
|
});
|
|
95
99
|
|
|
100
|
+
const {
|
|
101
|
+
isLoading: sourceLoading,
|
|
102
|
+
response: sourceResponse,
|
|
103
|
+
error: sourceError,
|
|
104
|
+
} = useQuery(queryClient, profileSource, QueryRequest_ReportType.SOURCE, {
|
|
105
|
+
skip: !dashboardItems.includes('source'),
|
|
106
|
+
sourceBuildID,
|
|
107
|
+
sourceFilename,
|
|
108
|
+
});
|
|
109
|
+
|
|
96
110
|
useEffect(() => {
|
|
97
111
|
if (
|
|
98
112
|
(!flamegraphLoading && flamegraphResponse?.report.oneofKind === 'flamegraph') ||
|
|
@@ -101,20 +115,26 @@ export const ProfileViewWithData = ({
|
|
|
101
115
|
perf?.markInteraction('Flamegraph render', flamegraphResponse.total);
|
|
102
116
|
}
|
|
103
117
|
|
|
104
|
-
if (!
|
|
105
|
-
perf?.markInteraction('
|
|
118
|
+
if (!tableLoading && tableResponse?.report.oneofKind === 'tableArrow') {
|
|
119
|
+
perf?.markInteraction('table render', tableResponse.total);
|
|
106
120
|
}
|
|
107
121
|
|
|
108
122
|
if (!callgraphLoading && callgraphResponse?.report.oneofKind === 'callgraph') {
|
|
109
123
|
perf?.markInteraction('Callgraph render', callgraphResponse.total);
|
|
110
124
|
}
|
|
125
|
+
|
|
126
|
+
if (!sourceLoading && sourceResponse?.report.oneofKind === 'source') {
|
|
127
|
+
perf?.markInteraction('Source render', sourceResponse.total);
|
|
128
|
+
}
|
|
111
129
|
}, [
|
|
112
130
|
flamegraphLoading,
|
|
113
131
|
flamegraphResponse,
|
|
114
132
|
callgraphResponse,
|
|
115
133
|
callgraphLoading,
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
tableLoading,
|
|
135
|
+
tableResponse,
|
|
136
|
+
sourceLoading,
|
|
137
|
+
sourceResponse,
|
|
118
138
|
perf,
|
|
119
139
|
]);
|
|
120
140
|
|
|
@@ -143,12 +163,15 @@ export const ProfileViewWithData = ({
|
|
|
143
163
|
if (flamegraphResponse !== null) {
|
|
144
164
|
total = BigInt(flamegraphResponse.total);
|
|
145
165
|
filtered = BigInt(flamegraphResponse.filtered);
|
|
146
|
-
} else if (
|
|
147
|
-
total = BigInt(
|
|
148
|
-
filtered = BigInt(
|
|
166
|
+
} else if (tableResponse !== null) {
|
|
167
|
+
total = BigInt(tableResponse.total);
|
|
168
|
+
filtered = BigInt(tableResponse.filtered);
|
|
149
169
|
} else if (callgraphResponse !== null) {
|
|
150
170
|
total = BigInt(callgraphResponse.total);
|
|
151
171
|
filtered = BigInt(callgraphResponse.filtered);
|
|
172
|
+
} else if (sourceResponse !== null) {
|
|
173
|
+
total = BigInt(sourceResponse.total);
|
|
174
|
+
filtered = BigInt(sourceResponse.filtered);
|
|
152
175
|
}
|
|
153
176
|
|
|
154
177
|
return (
|
|
@@ -170,10 +193,12 @@ export const ProfileViewWithData = ({
|
|
|
170
193
|
error: flamegraphError,
|
|
171
194
|
}}
|
|
172
195
|
topTableData={{
|
|
173
|
-
loading:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
196
|
+
loading: tableLoading,
|
|
197
|
+
arrow:
|
|
198
|
+
tableResponse?.report.oneofKind === 'tableArrow'
|
|
199
|
+
? tableResponse.report.tableArrow
|
|
200
|
+
: undefined,
|
|
201
|
+
error: tableError,
|
|
177
202
|
}}
|
|
178
203
|
callgraphData={{
|
|
179
204
|
loading: callgraphLoading,
|
|
@@ -183,6 +208,14 @@ export const ProfileViewWithData = ({
|
|
|
183
208
|
: undefined,
|
|
184
209
|
error: callgraphError,
|
|
185
210
|
}}
|
|
211
|
+
sourceData={{
|
|
212
|
+
loading: sourceLoading,
|
|
213
|
+
data:
|
|
214
|
+
sourceResponse?.report.oneofKind === 'source'
|
|
215
|
+
? sourceResponse?.report?.source
|
|
216
|
+
: undefined,
|
|
217
|
+
error: sourceError,
|
|
218
|
+
}}
|
|
186
219
|
sampleUnit={sampleUnit}
|
|
187
220
|
profileSource={profileSource}
|
|
188
221
|
queryClient={queryClient}
|