Skip to content

Commit

Permalink
feat: Session usage monitor in react
Browse files Browse the repository at this point in the history
  • Loading branch information
ironAiken2 committed Nov 5, 2024
1 parent 3a72c18 commit 3a48b36
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 1 deletion.
7 changes: 6 additions & 1 deletion react/src/components/SessionDetailContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import SessionStatusTag from './ComputeSessionNodeItems/SessionStatusTag';
import SessionTypeTag from './ComputeSessionNodeItems/SessionTypeTag';
import Flex from './Flex';
import ImageMetaIcon from './ImageMetaIcon';
import SessionUsageMonitor from './SessionUsageMonitor';
import { SessionDetailContentQuery } from './__generated__/SessionDetailContentQuery.graphql';
import {
Alert,
Expand Down Expand Up @@ -80,6 +81,7 @@ const SessionDetailContent: React.FC<{
# fix: This fragment is not used in this component, but it is required by the SessionActionButtonsFragment.
# It might be a bug in relay
...ContainerLogModalFragment
...SessionUsageMonitorFragment
}
legacy_session: compute_session(id: $uuid) {
image
Expand Down Expand Up @@ -178,11 +180,14 @@ const SessionDetailContent: React.FC<{
<Descriptions.Item label={t('session.Agent')}>
{session.agent_ids || '-'}
</Descriptions.Item>
<Descriptions.Item label={t('session.Reservation')}>
<Descriptions.Item label={t('session.Reservation')} span={md ? 2 : 1}>
<Flex gap={'xs'} wrap={'wrap'}>
<SessionReservation sessionFrgmt={session} />
</Flex>
</Descriptions.Item>
<Descriptions.Item label={'Resource Usage'} span={md ? 2 : 1}>
<SessionUsageMonitor sessionFrgmt={session} col={md ? 2 : 1} />
</Descriptions.Item>
</Descriptions>
</Flex>
) : (
Expand Down
157 changes: 157 additions & 0 deletions react/src/components/SessionUsageMonitor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { bytesToGB, toFixedFloorWithoutTrailingZeros } from '../helper';
import Flex from './Flex';
import { ResourceTypeIcon } from './ResourceNumber';
import { SessionUsageMonitorFragment$key } from './__generated__/SessionUsageMonitorFragment.graphql';
import { Col, Progress, ProgressProps, Row, Typography, theme } from 'antd';
import { createStyles } from 'antd-style';
import graphql from 'babel-plugin-relay/macro';
import _ from 'lodash';
import { useFragment } from 'react-relay';

const useStyles = createStyles(({ css, token }) => ({
progress: css`
.ant-progress-text {
// color: ${token.colorWhite} !important;
font-size: ${token.fontSizeSM} !important;
}
.ant-typography {
color: ${token.colorTextSecondary} !important;
font-size: ${token.fontSizeSM}px !important;
}
`,
}));

interface SessionUsageMonitorProps extends ProgressProps {
sessionFrgmt: SessionUsageMonitorFragment$key | null;
col?: 1 | 2 | 3 | 4;
size?: ProgressProps['size'];
}

// compute session node query returns accelerator type as `[device_name]_[util|mem]`
// so we need to split via '_' and get the first part to map to the resource type in `resourceTypeIconSrcMap`
const resourceTypeMap = {
cpu: 'cpu',
mem: 'mem',
cuda: 'cuda.device',
rocm: 'rocm.device',
tpu: 'tpu.device',
ipu: 'ipu.device',
atom: 'atom.device',
'atom-plus': 'atom-plus.device',
gaudi2: 'gaudi2.device',
warboy: 'warboy.device',
rngd: 'rngd.device',
'hyperaccel-lpu': 'hyperaccel-lpu.device',
};

const gridColSpanMap = {
1: 24,
2: 12,
3: 8,
4: 6,
};

const SessionUsageMonitor: React.FC<SessionUsageMonitorProps> = ({
sessionFrgmt,
col = 1,
size = 'default',
}) => {
const { token } = theme.useToken();
const { styles } = useStyles();

const kernel_nodes = useFragment(
graphql`
fragment SessionUsageMonitorFragment on ComputeSessionNode {
kernel_nodes {
edges {
node {
live_stat
}
}
}
}
`,
sessionFrgmt,
);
const liveStat = JSON.parse(
_.get(kernel_nodes, 'kernel_nodes.edges[0].node.live_stat') ?? '{}',
);

console.log('#liveStat: ', liveStat);
return (
<>
<Row className={styles.progress} gutter={token.marginXS}>
{liveStat?.cpu_util ? (
<Col
span={_.get(gridColSpanMap, col)}
style={{ marginBottom: token.marginXS }}
>
<Flex direction="column" align="end">
<Flex
align="start"
gap={token.marginSM}
style={{ width: '100%' }}
>
<ResourceTypeIcon
type={resourceTypeMap.cpu}
showTooltip={true}
/>
<Progress
percent={_.toNumber(
toFixedFloorWithoutTrailingZeros(
liveStat?.cpu_util?.pct || 0,
1,
),
)}
strokeLinecap="butt"
showInfo={true}
// percentPosition={{ align: 'end', type: 'inner' }}
size={size === 'default' ? { height: 20 } : size}
// strokeColor={token.colorPrimary}
></Progress>
</Flex>
{size === 'small' ? (
<Typography.Text>
{`${liveStat?.cpu_util?.pct} %`}
</Typography.Text>
) : null}
</Flex>
</Col>
) : null}
{liveStat?.mem ? (
<Col
span={_.get(gridColSpanMap, col)}
style={{ marginBottom: token.marginXS }}
>
<Flex direction="column" align="end">
<Flex gap={token.marginSM} style={{ width: '100%' }}>
<ResourceTypeIcon
type={resourceTypeMap.mem}
showTooltip={true}
/>
<Progress
percent={_.toNumber(
toFixedFloorWithoutTrailingZeros(
liveStat?.mem?.pct || 0,
1,
),
)}
strokeLinecap="butt"
percentPosition={{ align: 'end', type: 'inner' }}
size={{ height: 20 }}
strokeColor={token.colorPrimary}
></Progress>
</Flex>
<Typography.Text>
{`${bytesToGB(liveStat?.mem?.current)} / ${bytesToGB(liveStat?.mem?.capacity)} GB`}
</Typography.Text>
</Flex>
</Col>
) : null}
{}
</Row>
</>
);
};

export default SessionUsageMonitor;

0 comments on commit 3a48b36

Please sign in to comment.