Skip to content

Commit 4c5befa

Browse files
committed
Only hide the metrics graph
1 parent 54f3e0c commit 4c5befa

File tree

4 files changed

+150
-146
lines changed

4 files changed

+150
-146
lines changed

ui/packages/shared/profile/src/ProfileExplorer/ProfileExplorerCompare.tsx

+34-47
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
import {useState} from 'react';
1515

16-
import cx from 'classnames';
17-
1816
import {QueryServiceClient} from '@parca/client';
1917
import {useURLState} from '@parca/components';
2018
import {Query} from '@parca/parser';
@@ -79,51 +77,40 @@ const ProfileExplorerCompare = ({
7977
setShowButton(false);
8078
}}
8179
>
82-
<button
83-
onClick={() => setShowMetricsGraph(!showMetricsGraph)}
84-
className={cx(
85-
'hidden right-0 bottom-3 z-10 px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900',
86-
showButton && showMetricsGraph && 'absolute !flex',
87-
!showMetricsGraph && 'relative !flex mt-3 ml-auto'
88-
)}
89-
>
90-
{showMetricsGraph ? 'Hide' : 'Show'} Metrics Graph
91-
</button>
92-
93-
{showMetricsGraph ? (
94-
<>
95-
<div className="flex-column flex-1 p-2 shadow-md rounded-md">
96-
<ProfileSelector
97-
queryClient={queryClient}
98-
querySelection={queryA}
99-
profileSelection={profileA}
100-
selectProfile={selectProfileA}
101-
selectQuery={selectQueryA}
102-
closeProfile={closeProfileA}
103-
enforcedProfileName={''}
104-
comparing={true}
105-
navigateTo={navigateTo}
106-
suffix="_a"
107-
/>
108-
</div>
109-
<div className="flex-column flex-1 p-2 shadow-md rounded-md">
110-
<ProfileSelector
111-
queryClient={queryClient}
112-
querySelection={queryB}
113-
profileSelection={profileB}
114-
selectProfile={selectProfileB}
115-
selectQuery={selectQueryB}
116-
closeProfile={closeProfileB}
117-
enforcedProfileName={Query.parse(queryA.expression).profileName()}
118-
comparing={true}
119-
navigateTo={navigateTo}
120-
suffix="_b"
121-
/>
122-
</div>
123-
</>
124-
) : (
125-
<></>
126-
)}
80+
<div className="flex-column flex-1 p-2 shadow-md rounded-md">
81+
<ProfileSelector
82+
queryClient={queryClient}
83+
querySelection={queryA}
84+
profileSelection={profileA}
85+
selectProfile={selectProfileA}
86+
selectQuery={selectQueryA}
87+
closeProfile={closeProfileA}
88+
enforcedProfileName={''}
89+
comparing={true}
90+
navigateTo={navigateTo}
91+
suffix="_a"
92+
showMetricsGraph={showMetricsGraph}
93+
displayHideMetricsGraphButton={showButton}
94+
setDisplayHideMetricsGraphButton={setShowMetricsGraph}
95+
/>
96+
</div>
97+
<div className="flex-column flex-1 p-2 shadow-md rounded-md">
98+
<ProfileSelector
99+
queryClient={queryClient}
100+
querySelection={queryB}
101+
profileSelection={profileB}
102+
selectProfile={selectProfileB}
103+
selectQuery={selectQueryB}
104+
closeProfile={closeProfileB}
105+
enforcedProfileName={Query.parse(queryA.expression).profileName()}
106+
comparing={true}
107+
navigateTo={navigateTo}
108+
suffix="_b"
109+
showMetricsGraph={showMetricsGraph}
110+
displayHideMetricsGraphButton={showButton}
111+
setDisplayHideMetricsGraphButton={setShowMetricsGraph}
112+
/>
113+
</div>
127114
</div>
128115
<div className="grid grid-cols-1">
129116
{profileA != null && profileB != null ? (

ui/packages/shared/profile/src/ProfileExplorer/ProfileExplorerSingle.tsx

+15-29
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
import {useState} from 'react';
1515

16-
import cx from 'classnames';
17-
1816
import {QueryServiceClient} from '@parca/client';
1917
import type {NavigateFunction} from '@parca/utilities';
2018

@@ -54,33 +52,21 @@ const ProfileExplorerSingle = ({
5452
setShowButton(false);
5553
}}
5654
>
57-
<button
58-
onClick={() => setShowMetricsGraph(!showMetricsGraph)}
59-
className={cx(
60-
'hidden right-0 bottom-3 z-10 px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900',
61-
showButton && showMetricsGraph && 'absolute !flex',
62-
!showMetricsGraph && 'relative !flex mt-3 ml-auto'
63-
)}
64-
>
65-
{showMetricsGraph ? 'Hide' : 'Show'} Metrics Graph
66-
</button>
67-
68-
{showMetricsGraph ? (
69-
<ProfileSelector
70-
queryClient={queryClient}
71-
querySelection={query}
72-
selectQuery={selectQuery}
73-
selectProfile={selectProfile}
74-
closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
75-
profileSelection={profile}
76-
comparing={false}
77-
enforcedProfileName={''} // TODO
78-
navigateTo={navigateTo}
79-
suffix="_a"
80-
/>
81-
) : (
82-
<></>
83-
)}
55+
<ProfileSelector
56+
queryClient={queryClient}
57+
querySelection={query}
58+
selectQuery={selectQuery}
59+
selectProfile={selectProfile}
60+
closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
61+
profileSelection={profile}
62+
comparing={false}
63+
enforcedProfileName={''} // TODO
64+
navigateTo={navigateTo}
65+
suffix="_a"
66+
showMetricsGraph={showMetricsGraph}
67+
displayHideMetricsGraphButton={showButton}
68+
setDisplayHideMetricsGraphButton={setShowMetricsGraph}
69+
/>
8470
</div>
8571

8672
{profile != null ? (

ui/packages/shared/profile/src/ProfileSelector/index.tsx

+91-68
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import React, {useEffect, useMemo, useRef, useState} from 'react';
1515

1616
import {Switch} from '@headlessui/react';
1717
import {RpcError} from '@protobuf-ts/runtime-rpc';
18+
import cx from 'classnames';
1819
import Select, {type SelectInstance} from 'react-select';
1920

2021
import {Label, ProfileTypesResponse, QueryServiceClient} from '@parca/client';
@@ -63,6 +64,9 @@ interface ProfileSelectorProps {
6364
comparing: boolean;
6465
navigateTo: NavigateFunction;
6566
suffix?: string;
67+
showMetricsGraph: boolean;
68+
displayHideMetricsGraphButton: boolean;
69+
setDisplayHideMetricsGraphButton: Dispatch<SetStateAction<boolean>>;
6670
}
6771

6872
export interface IProfileTypesResult {
@@ -101,6 +105,9 @@ const ProfileSelector = ({
101105
profileSelection,
102106
comparing,
103107
navigateTo,
108+
showMetricsGraph,
109+
displayHideMetricsGraphButton,
110+
setDisplayHideMetricsGraphButton,
104111
}: ProfileSelectorProps): JSX.Element => {
105112
const {
106113
loading: profileTypesLoading,
@@ -427,75 +434,91 @@ const ProfileSelector = ({
427434
</div>
428435
<div>{comparing && <IconButton onClick={() => closeProfile()} icon={<CloseIcon />} />}</div>
429436
</div>
430-
<div>
431-
<div style={{height: heightStyle}}>
432-
{querySelection.expression !== undefined &&
433-
querySelection.expression.length > 0 &&
434-
querySelection.from !== undefined &&
435-
querySelection.to !== undefined ? (
436-
<div>
437-
<ProfileMetricsGraph
438-
queryClient={queryClient}
439-
queryExpression={querySelection.expression}
440-
from={querySelection.from}
441-
to={querySelection.to}
442-
profile={profileSelection}
443-
comparing={comparing}
444-
sumBy={querySelection.sumBy ?? defaultSumBy ?? []}
445-
sumByLoading={defaultSumByLoading}
446-
setTimeRange={(range: DateTimeRange) => {
447-
const from = range.getFromMs();
448-
const to = range.getToMs();
449-
let mergedProfileParams = {};
450-
if (query.profileType().delta) {
451-
mergedProfileParams = {mergeFrom: from, mergeTo: to};
452-
}
453-
setTimeRangeSelection(range);
454-
selectQuery({
455-
expression: queryExpressionString,
456-
from,
457-
to,
458-
timeSelection: range.getRangeKey(),
459-
...mergedProfileParams,
460-
});
461-
}}
462-
addLabelMatcher={addLabelMatcher}
463-
onPointClick={(
464-
timestamp: number,
465-
labels: Label[],
466-
queryExpression: string,
467-
duration: number
468-
) => {
469-
// TODO: Pass the query object via click rather than queryExpression
470-
let query = Query.parse(queryExpression);
471-
labels.forEach(l => {
472-
const [newQuery, updated] = query.setMatcher(l.name, l.value);
473-
if (updated) {
474-
query = newQuery;
475-
}
476-
});
477-
478-
const durationInMilliseconds = duration / 1000000; // duration is in nanoseconds
479-
const mergeFrom = timestamp;
480-
const mergeTo = query.profileType().delta
481-
? mergeFrom + durationInMilliseconds
482-
: mergeFrom;
483-
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
484-
}}
485-
/>
486-
</div>
487-
) : (
488-
<>
489-
{profileSelection == null ? (
490-
<div className="p-2">
491-
<ProfileMetricsEmptyState
492-
message={`Please select a profile type and click "Search" to begin.`}
493-
/>
494-
</div>
495-
) : null}
496-
</>
437+
<div
438+
className={cx('relative', {
439+
'py-4': !showMetricsGraph,
440+
})}
441+
>
442+
<button
443+
onClick={() => setDisplayHideMetricsGraphButton(!showMetricsGraph)}
444+
className={cx(
445+
'hidden z-10 px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900',
446+
displayHideMetricsGraphButton && showMetricsGraph && 'absolute right-0 bottom-3 !flex',
447+
!showMetricsGraph && 'relative !flex ml-auto'
497448
)}
498-
</div>
449+
>
450+
{showMetricsGraph ? 'Hide' : 'Show'} Metrics Graph
451+
</button>
452+
{showMetricsGraph ? (
453+
<div style={{height: heightStyle}}>
454+
{querySelection.expression !== undefined &&
455+
querySelection.expression.length > 0 &&
456+
querySelection.from !== undefined &&
457+
querySelection.to !== undefined ? (
458+
<div>
459+
<ProfileMetricsGraph
460+
queryClient={queryClient}
461+
queryExpression={querySelection.expression}
462+
from={querySelection.from}
463+
to={querySelection.to}
464+
profile={profileSelection}
465+
comparing={comparing}
466+
sumBy={querySelection.sumBy ?? defaultSumBy ?? []}
467+
sumByLoading={defaultSumByLoading}
468+
setTimeRange={(range: DateTimeRange) => {
469+
const from = range.getFromMs();
470+
const to = range.getToMs();
471+
let mergedProfileParams = {};
472+
if (query.profileType().delta) {
473+
mergedProfileParams = {mergeFrom: from, mergeTo: to};
474+
}
475+
setTimeRangeSelection(range);
476+
selectQuery({
477+
expression: queryExpressionString,
478+
from,
479+
to,
480+
timeSelection: range.getRangeKey(),
481+
...mergedProfileParams,
482+
});
483+
}}
484+
addLabelMatcher={addLabelMatcher}
485+
onPointClick={(
486+
timestamp: number,
487+
labels: Label[],
488+
queryExpression: string,
489+
duration: number
490+
) => {
491+
// TODO: Pass the query object via click rather than queryExpression
492+
let query = Query.parse(queryExpression);
493+
labels.forEach(l => {
494+
const [newQuery, updated] = query.setMatcher(l.name, l.value);
495+
if (updated) {
496+
query = newQuery;
497+
}
498+
});
499+
500+
const durationInMilliseconds = duration / 1000000; // duration is in nanoseconds
501+
const mergeFrom = timestamp;
502+
const mergeTo = query.profileType().delta
503+
? mergeFrom + durationInMilliseconds
504+
: mergeFrom;
505+
selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
506+
}}
507+
/>
508+
</div>
509+
) : (
510+
<>
511+
{profileSelection == null ? (
512+
<div className="p-2">
513+
<ProfileMetricsEmptyState
514+
message={`Please select a profile type and click "Search" to begin.`}
515+
/>
516+
</div>
517+
) : null}
518+
</>
519+
)}
520+
</div>
521+
) : null}
499522
</div>
500523
</>
501524
);

ui/packages/shared/profile/src/ProfileView/index.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,23 @@ export const ProfileView = ({
337337
[groupBy, setGroupBy]
338338
);
339339

340+
const showDivider =
341+
hasProfileSource &&
342+
(profileViewExternalMainActions === null || profileViewExternalMainActions === undefined);
343+
340344
return (
341345
<KeyDownProvider>
342346
<ProfileViewContextProvider value={{profileSource, compareMode}}>
343-
<div className="border-t border-gray-200 dark:border-gray-700 h-[1px] w-full pb-4"></div>
347+
{showDivider ? (
348+
<>
349+
<div className="border-t border-gray-200 dark:border-gray-700 h-[1px] w-full pb-4"></div>
350+
</>
351+
) : null}
344352
<div
345353
className={cx(
346354
'flex w-full',
347355
hasProfileSource || profileViewExternalMainActions != null
348-
? 'justify-center'
356+
? 'justify-start'
349357
: 'justify-end',
350358
{
351359
'items-end mb-4': !hasProfileSource && profileViewExternalMainActions != null,

0 commit comments

Comments
 (0)