@parca/profile 0.16.232 → 0.16.233
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 +1 -1
- package/dist/MetricsGraph/index.d.ts +2 -3
- package/dist/MetricsGraph/index.js +12 -11
- package/dist/MetricsGraph/useMetricsGraphDimensions.d.ts +0 -1
- package/dist/MetricsGraph/useMetricsGraphDimensions.js +0 -3
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +2 -1
- package/dist/ProfileExplorer/ProfileExplorerSingle.js +2 -1
- package/dist/ProfileIcicleGraph/index.js +1 -1
- package/dist/ProfileMetricsGraph/index.js +2 -2
- package/dist/ProfileSelector/index.js +38 -37
- package/dist/ProfileTypeSelector/index.js +1 -1
- package/dist/ProfileView/ViewSelector.d.ts +2 -1
- package/dist/ProfileView/ViewSelector.js +2 -2
- package/dist/ProfileView/VisualizationPanel.js +1 -1
- package/dist/ProfileView/index.js +12 -10
- package/dist/TopTable/index.js +1 -1
- package/dist/components/ProfileShareButton/index.js +2 -2
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/src/MatchersInput/index.tsx +1 -1
- package/src/MetricsGraph/index.tsx +83 -42
- package/src/MetricsGraph/useMetricsGraphDimensions.ts +0 -4
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +17 -12
- package/src/ProfileExplorer/ProfileExplorerSingle.tsx +21 -22
- package/src/ProfileIcicleGraph/index.tsx +1 -2
- package/src/ProfileMetricsGraph/index.tsx +2 -6
- package/src/ProfileSelector/index.tsx +70 -59
- package/src/ProfileTypeSelector/index.tsx +2 -1
- package/src/ProfileView/ViewSelector.tsx +3 -0
- package/src/ProfileView/VisualizationPanel.tsx +9 -6
- package/src/ProfileView/index.tsx +101 -93
- package/src/TopTable/index.tsx +11 -9
- package/src/components/ProfileShareButton/index.tsx +10 -3
|
@@ -43,7 +43,6 @@ interface Props {
|
|
|
43
43
|
width?: number;
|
|
44
44
|
height?: number;
|
|
45
45
|
margin?: number;
|
|
46
|
-
marginRight?: number;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
export interface HighlightedSeries {
|
|
@@ -75,7 +74,6 @@ const MetricsGraph = ({
|
|
|
75
74
|
width = 0,
|
|
76
75
|
height = 0,
|
|
77
76
|
margin = 0,
|
|
78
|
-
marginRight = 0,
|
|
79
77
|
}: Props): JSX.Element => {
|
|
80
78
|
return (
|
|
81
79
|
<RawMetricsGraph
|
|
@@ -90,7 +88,6 @@ const MetricsGraph = ({
|
|
|
90
88
|
width={width}
|
|
91
89
|
height={height}
|
|
92
90
|
margin={margin}
|
|
93
|
-
marginRight={marginRight}
|
|
94
91
|
/>
|
|
95
92
|
);
|
|
96
93
|
};
|
|
@@ -118,7 +115,6 @@ export const RawMetricsGraph = ({
|
|
|
118
115
|
width,
|
|
119
116
|
height = 50,
|
|
120
117
|
margin = 0,
|
|
121
|
-
marginRight = 0,
|
|
122
118
|
sampleUnit,
|
|
123
119
|
}: Props): JSX.Element => {
|
|
124
120
|
const graph = useRef(null);
|
|
@@ -174,13 +170,14 @@ export const RawMetricsGraph = ({
|
|
|
174
170
|
const xScale = d3
|
|
175
171
|
.scaleUtc()
|
|
176
172
|
.domain([from, to])
|
|
177
|
-
.range([0, width -
|
|
173
|
+
.range([0, width - 2 * margin]);
|
|
178
174
|
|
|
179
175
|
const yScale = d3
|
|
180
176
|
.scaleLinear()
|
|
181
177
|
// tslint:disable-next-line
|
|
182
178
|
.domain([minY, maxY] as Iterable<d3.NumberValue>)
|
|
183
|
-
.range([height - margin, 0])
|
|
179
|
+
.range([height - margin, 0])
|
|
180
|
+
.nice();
|
|
184
181
|
|
|
185
182
|
const color = d3.scaleOrdinal(d3.schemeCategory10);
|
|
186
183
|
|
|
@@ -360,6 +357,7 @@ export const RawMetricsGraph = ({
|
|
|
360
357
|
};
|
|
361
358
|
|
|
362
359
|
const selected = findSelectedProfile();
|
|
360
|
+
|
|
363
361
|
return (
|
|
364
362
|
<>
|
|
365
363
|
{highlighted != null && hovering && !dragging && pos[0] !== 0 && pos[1] !== 0 && (
|
|
@@ -408,6 +406,85 @@ export const RawMetricsGraph = ({
|
|
|
408
406
|
)}
|
|
409
407
|
</g>
|
|
410
408
|
<g transform={`translate(${margin}, ${margin})`}>
|
|
409
|
+
<g className="y axis" textAnchor="end" fontSize="10" fill="none">
|
|
410
|
+
{yScale.ticks(5).map((d, i) => (
|
|
411
|
+
<>
|
|
412
|
+
<g
|
|
413
|
+
key={`tick-${i}`}
|
|
414
|
+
className="tick"
|
|
415
|
+
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
416
|
+
transform={`translate(0, ${yScale(d)})`}
|
|
417
|
+
>
|
|
418
|
+
<line className="stroke-gray-300 dark:stroke-gray-500" x2={-6} />
|
|
419
|
+
<text fill="currentColor" x={-9} dy={'0.32em'}>
|
|
420
|
+
{valueFormatter(d, sampleUnit, 1)}
|
|
421
|
+
</text>
|
|
422
|
+
</g>
|
|
423
|
+
<g key={`grid-${i}`}>
|
|
424
|
+
<line
|
|
425
|
+
className="stroke-gray-300 dark:stroke-gray-500"
|
|
426
|
+
x1={xScale(from)}
|
|
427
|
+
x2={xScale(to)}
|
|
428
|
+
y1={yScale(d)}
|
|
429
|
+
y2={yScale(d)}
|
|
430
|
+
/>
|
|
431
|
+
</g>
|
|
432
|
+
</>
|
|
433
|
+
))}
|
|
434
|
+
<line
|
|
435
|
+
className="stroke-gray-300 dark:stroke-gray-500"
|
|
436
|
+
x1={0}
|
|
437
|
+
x2={0}
|
|
438
|
+
y1={0}
|
|
439
|
+
y2={height - margin}
|
|
440
|
+
/>
|
|
441
|
+
<line
|
|
442
|
+
className="stroke-gray-300 dark:stroke-gray-500"
|
|
443
|
+
x1={xScale(to)}
|
|
444
|
+
x2={xScale(to)}
|
|
445
|
+
y1={0}
|
|
446
|
+
y2={height - margin}
|
|
447
|
+
/>
|
|
448
|
+
</g>
|
|
449
|
+
<g
|
|
450
|
+
className="x axis"
|
|
451
|
+
fill="none"
|
|
452
|
+
fontSize="10"
|
|
453
|
+
textAnchor="middle"
|
|
454
|
+
transform={`translate(0,${height - margin})`}
|
|
455
|
+
>
|
|
456
|
+
{xScale.ticks(5).map((d, i) => (
|
|
457
|
+
<>
|
|
458
|
+
<g
|
|
459
|
+
key={`tick-${i}`}
|
|
460
|
+
className="tick"
|
|
461
|
+
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
462
|
+
transform={`translate(${xScale(d)}, 0)`}
|
|
463
|
+
>
|
|
464
|
+
<line y2={6} className="stroke-gray-300 dark:stroke-gray-500" />
|
|
465
|
+
<text fill="currentColor" dy=".71em" y={9}>
|
|
466
|
+
{formatDate(d, formatForTimespan(from, to))}
|
|
467
|
+
</text>
|
|
468
|
+
</g>
|
|
469
|
+
<g key={`grid-${i}`}>
|
|
470
|
+
<line
|
|
471
|
+
className="stroke-gray-300 dark:stroke-gray-500"
|
|
472
|
+
x1={xScale(d)}
|
|
473
|
+
x2={xScale(d)}
|
|
474
|
+
y1={0}
|
|
475
|
+
y2={-height + margin}
|
|
476
|
+
/>
|
|
477
|
+
</g>
|
|
478
|
+
</>
|
|
479
|
+
))}
|
|
480
|
+
<line
|
|
481
|
+
className="stroke-gray-300 dark:stroke-gray-500"
|
|
482
|
+
x1={xScale(from)}
|
|
483
|
+
x2={xScale(to)}
|
|
484
|
+
y1={0}
|
|
485
|
+
y2={0}
|
|
486
|
+
/>
|
|
487
|
+
</g>
|
|
411
488
|
<g className="lines fill-transparent">
|
|
412
489
|
{series.map((s, i) => (
|
|
413
490
|
<g key={i} className="line">
|
|
@@ -447,42 +524,6 @@ export const RawMetricsGraph = ({
|
|
|
447
524
|
<MetricsCircle cx={selected.x} cy={selected.y} radius={5} />
|
|
448
525
|
</g>
|
|
449
526
|
)}
|
|
450
|
-
<g
|
|
451
|
-
className="x axis"
|
|
452
|
-
fill="none"
|
|
453
|
-
fontSize="10"
|
|
454
|
-
textAnchor="middle"
|
|
455
|
-
transform={`translate(0,${height - margin})`}
|
|
456
|
-
>
|
|
457
|
-
{xScale.ticks(5).map((d, i) => (
|
|
458
|
-
<g
|
|
459
|
-
key={i}
|
|
460
|
-
className="tick"
|
|
461
|
-
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
462
|
-
transform={`translate(${xScale(d)}, 0)`}
|
|
463
|
-
>
|
|
464
|
-
<line y2={6} stroke="currentColor" />
|
|
465
|
-
<text fill="currentColor" dy=".71em" y={9}>
|
|
466
|
-
{formatDate(d, formatForTimespan(from, to))}
|
|
467
|
-
</text>
|
|
468
|
-
</g>
|
|
469
|
-
))}
|
|
470
|
-
</g>
|
|
471
|
-
<g className="y axis" textAnchor="end" fontSize="10" fill="none">
|
|
472
|
-
{yScale.ticks(3).map((d, i) => (
|
|
473
|
-
<g
|
|
474
|
-
key={i}
|
|
475
|
-
className="tick"
|
|
476
|
-
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
|
|
477
|
-
transform={`translate(0, ${yScale(d)})`}
|
|
478
|
-
>
|
|
479
|
-
<line stroke="currentColor" x2={-6} />
|
|
480
|
-
<text fill="currentColor" x={-9} dy={'0.32em'}>
|
|
481
|
-
{valueFormatter(d, sampleUnit, 1)}
|
|
482
|
-
</text>
|
|
483
|
-
</g>
|
|
484
|
-
))}
|
|
485
|
-
</g>
|
|
486
527
|
</g>
|
|
487
528
|
</svg>
|
|
488
529
|
</div>
|
|
@@ -20,7 +20,6 @@ interface MetricsGraphDimensions {
|
|
|
20
20
|
height: number;
|
|
21
21
|
heightStyle: string;
|
|
22
22
|
margin: number;
|
|
23
|
-
marginRight: number;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
const maxHeight = 402;
|
|
@@ -35,7 +34,6 @@ export const useMetricsGraphDimensions = (comparing: boolean): MetricsGraphDimen
|
|
|
35
34
|
height: 0,
|
|
36
35
|
heightStyle: '0',
|
|
37
36
|
margin: 0,
|
|
38
|
-
marginRight: 0,
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
39
|
width = width - profileExplorer.PaddingX;
|
|
@@ -43,7 +41,6 @@ export const useMetricsGraphDimensions = (comparing: boolean): MetricsGraphDimen
|
|
|
43
41
|
width = width / 2 - 32;
|
|
44
42
|
}
|
|
45
43
|
const height = Math.min(width / 2.5, maxHeight);
|
|
46
|
-
const marginRight = 20;
|
|
47
44
|
const heightStyle = `min(${maxHeight + margin}px, ${
|
|
48
45
|
comparing
|
|
49
46
|
? profileExplorer.metricsGraph.maxHeightStyle.compareMode
|
|
@@ -54,6 +51,5 @@ export const useMetricsGraphDimensions = (comparing: boolean): MetricsGraphDimen
|
|
|
54
51
|
height,
|
|
55
52
|
heightStyle,
|
|
56
53
|
margin,
|
|
57
|
-
marginRight,
|
|
58
54
|
};
|
|
59
55
|
};
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
14
|
import {QueryServiceClient} from '@parca/client';
|
|
15
|
+
import {Card} from '@parca/components';
|
|
15
16
|
import {Query} from '@parca/parser';
|
|
16
17
|
import type {NavigateFunction} from '@parca/utilities';
|
|
17
18
|
|
|
@@ -57,8 +58,8 @@ const ProfileExplorerCompare = ({
|
|
|
57
58
|
|
|
58
59
|
return (
|
|
59
60
|
<>
|
|
60
|
-
<div className="
|
|
61
|
-
<
|
|
61
|
+
<div className="flex justify-between gap-2">
|
|
62
|
+
<Card className="p-2">
|
|
62
63
|
<ProfileSelector
|
|
63
64
|
queryClient={queryClient}
|
|
64
65
|
querySelection={queryA}
|
|
@@ -70,8 +71,8 @@ const ProfileExplorerCompare = ({
|
|
|
70
71
|
comparing={true}
|
|
71
72
|
onCompareProfile={() => {}}
|
|
72
73
|
/>
|
|
73
|
-
</
|
|
74
|
-
<
|
|
74
|
+
</Card>
|
|
75
|
+
<Card className="p-2">
|
|
75
76
|
<ProfileSelector
|
|
76
77
|
queryClient={queryClient}
|
|
77
78
|
querySelection={queryB}
|
|
@@ -83,17 +84,21 @@ const ProfileExplorerCompare = ({
|
|
|
83
84
|
comparing={true}
|
|
84
85
|
onCompareProfile={() => {}}
|
|
85
86
|
/>
|
|
86
|
-
</
|
|
87
|
+
</Card>
|
|
87
88
|
</div>
|
|
88
89
|
<div className="grid grid-cols-1">
|
|
89
90
|
{profileA != null && profileB != null ? (
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
<div className="mt-2">
|
|
92
|
+
<Card className="px-6 py-4">
|
|
93
|
+
<ProfileViewWithData
|
|
94
|
+
navigateTo={navigateTo}
|
|
95
|
+
queryClient={queryClient}
|
|
96
|
+
profileSource={
|
|
97
|
+
new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource())
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
</Card>
|
|
101
|
+
</div>
|
|
97
102
|
) : (
|
|
98
103
|
<div>
|
|
99
104
|
<div className="my-20 text-center">
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
14
|
import {QueryServiceClient} from '@parca/client';
|
|
15
|
+
import {Card} from '@parca/components';
|
|
15
16
|
import type {NavigateFunction} from '@parca/utilities';
|
|
16
17
|
|
|
17
18
|
import {ProfileSelection, ProfileViewWithData} from '..';
|
|
@@ -38,34 +39,32 @@ const ProfileExplorerSingle = ({
|
|
|
38
39
|
}: ProfileExplorerSingleProps): JSX.Element => {
|
|
39
40
|
return (
|
|
40
41
|
<>
|
|
41
|
-
<
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div>
|
|
58
|
-
{profile != null ? (
|
|
42
|
+
<Card className="px-6 py-4">
|
|
43
|
+
<ProfileSelector
|
|
44
|
+
queryClient={queryClient}
|
|
45
|
+
querySelection={query}
|
|
46
|
+
selectQuery={selectQuery}
|
|
47
|
+
selectProfile={selectProfile}
|
|
48
|
+
closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
|
|
49
|
+
profileSelection={profile}
|
|
50
|
+
comparing={false}
|
|
51
|
+
onCompareProfile={compareProfile}
|
|
52
|
+
enforcedProfileName={''} // TODO
|
|
53
|
+
/>
|
|
54
|
+
</Card>
|
|
55
|
+
{profile != null ? (
|
|
56
|
+
<div className="mt-2">
|
|
57
|
+
<Card className="px-6 py-4">
|
|
59
58
|
<ProfileViewWithData
|
|
60
59
|
queryClient={queryClient}
|
|
61
60
|
profileSource={profile.ProfileSource()}
|
|
62
61
|
navigateTo={navigateTo}
|
|
63
62
|
/>
|
|
64
|
-
|
|
65
|
-
<></>
|
|
66
|
-
)}
|
|
63
|
+
</Card>
|
|
67
64
|
</div>
|
|
68
|
-
|
|
65
|
+
) : (
|
|
66
|
+
<></>
|
|
67
|
+
)}
|
|
69
68
|
</>
|
|
70
69
|
);
|
|
71
70
|
};
|
|
@@ -158,10 +158,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
|
|
|
158
158
|
}
|
|
159
159
|
setActionButtons(
|
|
160
160
|
<div className="flex w-full justify-end gap-2 pb-2">
|
|
161
|
-
<div className="flex w-full items-
|
|
161
|
+
<div className="ml-2 flex w-full items-end justify-between gap-2">
|
|
162
162
|
{table !== undefined && <GroupAndSortActionButtons navigateTo={navigateTo} />}
|
|
163
163
|
<div>
|
|
164
|
-
<label className="inline-block"></label>
|
|
165
164
|
<Button
|
|
166
165
|
color="neutral"
|
|
167
166
|
onClick={() => setNewCurPath([])}
|
|
@@ -115,7 +115,7 @@ const ProfileMetricsGraph = ({
|
|
|
115
115
|
const {isLoading, response, error} = useQueryRange(queryClient, queryExpression, from, to);
|
|
116
116
|
const isLoaderVisible = useDelayedLoader(isLoading);
|
|
117
117
|
const {loader, onError, perf} = useParcaContext();
|
|
118
|
-
const {width, height, margin
|
|
118
|
+
const {width, height, margin} = useMetricsGraphDimensions(comparing);
|
|
119
119
|
|
|
120
120
|
useEffect(() => {
|
|
121
121
|
if (error !== null) {
|
|
@@ -156,10 +156,7 @@ const ProfileMetricsGraph = ({
|
|
|
156
156
|
};
|
|
157
157
|
|
|
158
158
|
return (
|
|
159
|
-
<div
|
|
160
|
-
className="h-full w-full rounded border-gray-300 dark:border-gray-500 dark:bg-gray-700"
|
|
161
|
-
style={{borderWidth: 1}}
|
|
162
|
-
>
|
|
159
|
+
<div className="h-full w-full">
|
|
163
160
|
<MetricsGraph
|
|
164
161
|
data={series}
|
|
165
162
|
from={from}
|
|
@@ -172,7 +169,6 @@ const ProfileMetricsGraph = ({
|
|
|
172
169
|
height={height}
|
|
173
170
|
width={width}
|
|
174
171
|
margin={margin}
|
|
175
|
-
marginRight={marginRight}
|
|
176
172
|
/>
|
|
177
173
|
</div>
|
|
178
174
|
);
|
|
@@ -19,7 +19,6 @@ import {ProfileTypesResponse, QueryServiceClient} from '@parca/client';
|
|
|
19
19
|
import {
|
|
20
20
|
Button,
|
|
21
21
|
ButtonGroup,
|
|
22
|
-
Card,
|
|
23
22
|
DateTimeRange,
|
|
24
23
|
DateTimeRangePicker,
|
|
25
24
|
IconButton,
|
|
@@ -198,59 +197,69 @@ const ProfileSelector = ({
|
|
|
198
197
|
|
|
199
198
|
const compareDisabled = selectedProfileName === '' || querySelection.expression === undefined;
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
<
|
|
203
|
-
<
|
|
204
|
-
<div
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
200
|
+
const Header = (): JSX.Element => (
|
|
201
|
+
<div className="mb-2 flex">
|
|
202
|
+
<div className="flex w-full flex-wrap content-start items-end justify-between gap-2">
|
|
203
|
+
<div>
|
|
204
|
+
<label className="text-xs">Profile type</label>
|
|
205
|
+
<ProfileTypeSelector
|
|
206
|
+
profileTypesData={profileTypesData}
|
|
207
|
+
loading={profileTypesLoading}
|
|
208
|
+
selectedKey={selectedProfileName}
|
|
209
|
+
onSelection={setProfileName}
|
|
210
|
+
error={error}
|
|
211
|
+
/>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div className="w-full flex-1">
|
|
215
|
+
<label className="text-xs">Query</label>
|
|
216
|
+
<MatchersInput
|
|
217
|
+
queryClient={queryClient}
|
|
218
|
+
setMatchersString={setMatchersString}
|
|
219
|
+
runQuery={setQueryExpression}
|
|
220
|
+
currentQuery={query}
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
<div>
|
|
224
|
+
<label className="text-xs">Period</label>
|
|
222
225
|
<DateTimeRangePicker
|
|
223
226
|
onRangeSelection={setTimeRangeSelection}
|
|
224
227
|
range={timeRangeSelection}
|
|
225
228
|
/>
|
|
226
|
-
<ButtonGroup>
|
|
227
|
-
{!searchDisabled && (
|
|
228
|
-
<>
|
|
229
|
-
{!comparing && (
|
|
230
|
-
<CompareButton disabled={compareDisabled} onClick={handleCompareClick} />
|
|
231
|
-
)}
|
|
232
|
-
</>
|
|
233
|
-
)}
|
|
234
|
-
<Button
|
|
235
|
-
disabled={searchDisabled}
|
|
236
|
-
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
|
237
|
-
e.preventDefault();
|
|
238
|
-
setQueryExpression();
|
|
239
|
-
}}
|
|
240
|
-
>
|
|
241
|
-
Search
|
|
242
|
-
</Button>
|
|
243
|
-
</ButtonGroup>
|
|
244
229
|
</div>
|
|
245
|
-
<
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
230
|
+
<ButtonGroup>
|
|
231
|
+
{!searchDisabled && (
|
|
232
|
+
<>
|
|
233
|
+
{!comparing && (
|
|
234
|
+
<CompareButton disabled={compareDisabled} onClick={handleCompareClick} />
|
|
235
|
+
)}
|
|
236
|
+
</>
|
|
237
|
+
)}
|
|
238
|
+
<Button
|
|
239
|
+
disabled={searchDisabled}
|
|
240
|
+
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
|
241
|
+
e.preventDefault();
|
|
242
|
+
setQueryExpression();
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
Search
|
|
246
|
+
</Button>
|
|
247
|
+
</ButtonGroup>
|
|
248
|
+
</div>
|
|
249
|
+
<div>{comparing && <IconButton onClick={() => closeProfile()} icon={<CloseIcon />} />}</div>
|
|
250
|
+
</div>
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<>
|
|
255
|
+
<Header />
|
|
256
|
+
<div className="rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700">
|
|
257
|
+
<div style={{height: heightStyle}}>
|
|
258
|
+
{querySelection.expression !== undefined &&
|
|
259
|
+
querySelection.expression.length > 0 &&
|
|
260
|
+
querySelection.from !== undefined &&
|
|
261
|
+
querySelection.to !== undefined ? (
|
|
262
|
+
<div className="p-2">
|
|
254
263
|
<ProfileMetricsGraph
|
|
255
264
|
queryClient={queryClient}
|
|
256
265
|
queryExpression={querySelection.expression}
|
|
@@ -294,19 +303,21 @@ const ProfileSelector = ({
|
|
|
294
303
|
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
|
|
295
304
|
}}
|
|
296
305
|
/>
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
</div>
|
|
307
|
+
) : (
|
|
308
|
+
<>
|
|
309
|
+
{profileSelection == null ? (
|
|
310
|
+
<div className="p-2">
|
|
300
311
|
<ProfileMetricsEmptyState
|
|
301
312
|
message={`Please select a profile type and click "Search" to begin.`}
|
|
302
313
|
/>
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
</
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
</div>
|
|
315
|
+
) : null}
|
|
316
|
+
</>
|
|
317
|
+
)}
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
</>
|
|
310
321
|
);
|
|
311
322
|
};
|
|
312
323
|
|
|
@@ -175,8 +175,9 @@ const ProfileTypeSelector = ({
|
|
|
175
175
|
items={profileLabels}
|
|
176
176
|
selectedKey={selectedKey}
|
|
177
177
|
onSelection={onSelection}
|
|
178
|
-
placeholder="Select profile..."
|
|
178
|
+
placeholder="Select profile type..."
|
|
179
179
|
loading={loading}
|
|
180
|
+
className="bg-white"
|
|
180
181
|
/>
|
|
181
182
|
);
|
|
182
183
|
};
|
|
@@ -23,6 +23,7 @@ interface Props {
|
|
|
23
23
|
primary?: boolean;
|
|
24
24
|
addView?: boolean;
|
|
25
25
|
disabled?: boolean;
|
|
26
|
+
icon?: JSX.Element;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const ViewSelector = ({
|
|
@@ -33,6 +34,7 @@ const ViewSelector = ({
|
|
|
33
34
|
primary = false,
|
|
34
35
|
addView = false,
|
|
35
36
|
disabled = false,
|
|
37
|
+
icon,
|
|
36
38
|
}: Props): JSX.Element => {
|
|
37
39
|
const [callgraphEnabled] = useUIFeatureFlag('callgraph');
|
|
38
40
|
const [dashboardItems = ['icicle'], setDashboardItems] = useURLState({
|
|
@@ -114,6 +116,7 @@ const ViewSelector = ({
|
|
|
114
116
|
placeholder={placeholderText ?? 'Select view type...'}
|
|
115
117
|
primary={primary}
|
|
116
118
|
disabled={disabled}
|
|
119
|
+
icon={icon}
|
|
117
120
|
/>
|
|
118
121
|
);
|
|
119
122
|
};
|
|
@@ -50,22 +50,25 @@ export const VisualizationPanel = React.memo(function VisualizationPanel({
|
|
|
50
50
|
|
|
51
51
|
return (
|
|
52
52
|
<>
|
|
53
|
-
<div className="flex w-full justify-end gap-2 pb-2">
|
|
54
|
-
<div className="flex w-full items-
|
|
55
|
-
<div className="flex">
|
|
53
|
+
<div className="flex w-full items-start justify-end gap-2 pb-2">
|
|
54
|
+
<div className="flex w-full items-start justify-between">
|
|
55
|
+
<div className="flex items-start">
|
|
56
56
|
<div
|
|
57
57
|
className={cx(isMultiPanelView ? 'visible' : 'invisible', 'flex items-center')}
|
|
58
58
|
{...dragHandleProps}
|
|
59
59
|
>
|
|
60
60
|
<Icon className="text-xl" icon="material-symbols:drag-indicator" />
|
|
61
61
|
</div>
|
|
62
|
-
|
|
62
|
+
<div>{actionButtons}</div>
|
|
63
63
|
</div>
|
|
64
64
|
<ViewSelector defaultValue={dashboardItem} navigateTo={navigateTo} position={index} />
|
|
65
65
|
</div>
|
|
66
|
-
|
|
67
66
|
{isMultiPanelView && (
|
|
68
|
-
<IconButton
|
|
67
|
+
<IconButton
|
|
68
|
+
className="py-0"
|
|
69
|
+
onClick={() => handleClosePanel(dashboardItem)}
|
|
70
|
+
icon={<CloseIcon />}
|
|
71
|
+
/>
|
|
69
72
|
)}
|
|
70
73
|
</div>
|
|
71
74
|
{getDashboardItemByType({
|