refactor + new account sync metrics + isolating health status inside folder admin-panel > health-status (#10314)

closes https://github.com/twentyhq/core-team-issues/issues/444
https://github.com/twentyhq/core-team-issues/issues/443
https://github.com/twentyhq/core-team-issues/issues/442
This commit is contained in:
nitin
2025-02-21 14:18:47 +05:30
committed by GitHub
parent 41bbb4b47f
commit c46f7848b7
57 changed files with 1441 additions and 833 deletions

View File

@ -1,44 +0,0 @@
import { Table } from '@/ui/layout/table/components/Table';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
export const SettingsAdminHealthMessageSyncCountersTable = ({
details,
}: {
details: string | null | undefined;
}) => {
const parsedDetails = details ? JSON.parse(details) : null;
if (!parsedDetails) {
return null;
}
return (
<Table>
<TableRow>
<TableHeader>Status</TableHeader>
<TableHeader align="right">Count</TableHeader>
</TableRow>
<TableRow>
<TableCell>Message Not Synced</TableCell>
<TableCell align="right">{parsedDetails.counters.NOT_SYNCED}</TableCell>
</TableRow>
<TableRow>
<TableCell>Message Sync Ongoing</TableCell>
<TableCell align="right">{parsedDetails.counters.ONGOING}</TableCell>
</TableRow>
<TableRow>
<TableCell>Total Jobs</TableCell>
<TableCell align="right">{parsedDetails.totalJobs}</TableCell>
</TableRow>
<TableRow>
<TableCell>Failed Jobs</TableCell>
<TableCell align="right">{parsedDetails.failedJobs}</TableCell>
</TableRow>
<TableRow>
<TableCell>Failure Rate</TableCell>
<TableCell align="right">{parsedDetails.failureRate}%</TableCell>
</TableRow>
</Table>
);
};

View File

@ -1,66 +0,0 @@
import { SettingsAdminHealthMessageSyncCountersTable } from '@/settings/admin-panel/components/SettingsAdminHealthMessageSyncCountersTable';
import { SettingsHealthStatusListCard } from '@/settings/admin-panel/components/SettingsHealthStatusListCard';
import { AdminHealthService } from '@/settings/admin-panel/types/AdminHealthService';
import styled from '@emotion/styled';
import { H2Title, Section } from 'twenty-ui';
import {
AdminPanelHealthServiceStatus,
useGetSystemHealthStatusQuery,
} from '~/generated/graphql';
const StyledErrorMessage = styled.div`
color: ${({ theme }) => theme.color.red};
margin-top: ${({ theme }) => theme.spacing(2)};
`;
export const SettingsAdminHealthStatus = () => {
const { data, loading } = useGetSystemHealthStatusQuery({
fetchPolicy: 'network-only',
});
const services = [
{
id: 'DATABASE',
name: 'Database Status',
...data?.getSystemHealthStatus.database,
},
{ id: 'REDIS', name: 'Redis Status', ...data?.getSystemHealthStatus.redis },
{
id: 'WORKER',
name: 'Worker Status',
status: data?.getSystemHealthStatus.worker.status,
queues: data?.getSystemHealthStatus.worker.queues,
},
].filter((service): service is AdminHealthService => !!service.status);
const isMessageSyncCounterDown =
!data?.getSystemHealthStatus.messageSync.status ||
data?.getSystemHealthStatus.messageSync.status ===
AdminPanelHealthServiceStatus.OUTAGE;
return (
<>
<Section>
<H2Title title="Health Status" description="How your system is doing" />
<SettingsHealthStatusListCard services={services} loading={loading} />
</Section>
<Section>
<H2Title
title="Message Sync Status"
description="How your message sync is doing"
/>
{isMessageSyncCounterDown ? (
<StyledErrorMessage>
{data?.getSystemHealthStatus.messageSync.details ||
'Message sync status is unavailable'}
</StyledErrorMessage>
) : (
<SettingsAdminHealthMessageSyncCountersTable
details={data?.getSystemHealthStatus.messageSync.details}
/>
)}
</Section>
</>
);
};

View File

@ -1,27 +0,0 @@
import { AdminHealthService } from '@/settings/admin-panel/types/AdminHealthService';
import styled from '@emotion/styled';
import { Status } from 'twenty-ui';
import { AdminPanelHealthServiceStatus } from '~/generated/graphql';
const StyledRowRightContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;
export const SettingsAdminHealthStatusRightContainer = ({
service,
}: {
service: AdminHealthService;
}) => {
return (
<StyledRowRightContainer>
{service.status === AdminPanelHealthServiceStatus.OPERATIONAL && (
<Status color="green" text="Operational" weight="medium" />
)}
{service.status === AdminPanelHealthServiceStatus.OUTAGE && (
<Status color="red" text="Outage" weight="medium" />
)}
</StyledRowRightContainer>
);
};

View File

@ -1,103 +0,0 @@
import { SettingsListCard } from '@/settings/components/SettingsListCard';
import { Table } from '@/ui/layout/table/components/Table';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import styled from '@emotion/styled';
import { AnimatedExpandableContainer, Status } from 'twenty-ui';
import {
AdminPanelHealthServiceStatus,
AdminPanelWorkerQueueHealth,
} from '~/generated/graphql';
const StyledExpandedContent = styled.div`
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding-top: ${({ theme }) => theme.spacing(1)};
padding-bottom: ${({ theme }) => theme.spacing(3)};
padding-left: ${({ theme }) => theme.spacing(3)};
padding-right: ${({ theme }) => theme.spacing(3)};
`;
const StyledContainer = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(3)};
margin-top: ${({ theme }) => theme.spacing(5)};
`;
const StyledTableRow = styled(TableRow)`
height: ${({ theme }) => theme.spacing(6)};
`;
const StyledQueueMetricsTitle = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin-bottom: ${({ theme }) => theme.spacing(3)};
padding-left: ${({ theme }) => theme.spacing(3)};
`;
export const SettingsAdminQueueExpandableContainer = ({
queues,
selectedQueue,
}: {
queues: AdminPanelWorkerQueueHealth[];
selectedQueue: string | null;
}) => {
const selectedQueueData = queues.find(
(queue) => queue.name === selectedQueue,
);
return (
<AnimatedExpandableContainer
isExpanded={!!selectedQueue}
mode="fit-content"
>
{selectedQueueData && (
<>
<StyledContainer>
<SettingsListCard
items={[{ ...selectedQueueData, id: selectedQueueData.name }]}
getItemLabel={(
item: AdminPanelWorkerQueueHealth & { id: string },
) => item.name}
isLoading={false}
RowRightComponent={({
item,
}: {
item: AdminPanelWorkerQueueHealth;
}) => (
<Status
color={
item.status === AdminPanelHealthServiceStatus.OPERATIONAL
? 'green'
: 'red'
}
text={item.status.toLowerCase()}
weight="medium"
/>
)}
/>
</StyledContainer>
<StyledQueueMetricsTitle> Metrics:</StyledQueueMetricsTitle>
<StyledExpandedContent>
<Table>
<StyledTableRow>
<TableCell align="left">Workers</TableCell>
<TableCell align="right">{selectedQueueData.workers}</TableCell>
</StyledTableRow>
{Object.entries(selectedQueueData.metrics)
.filter(([key]) => key !== '__typename')
.map(([key, value]) => (
<StyledTableRow key={key}>
<TableCell align="left">
{key.charAt(0).toUpperCase() + key.slice(1)}
</TableCell>
<TableCell align="right">{value}</TableCell>
</StyledTableRow>
))}
</Table>
</StyledExpandedContent>
</>
)}
</AnimatedExpandableContainer>
);
};

View File

@ -1,52 +0,0 @@
import styled from '@emotion/styled';
import { Button } from 'twenty-ui';
import {
AdminPanelHealthServiceStatus,
AdminPanelWorkerQueueHealth,
} from '~/generated/graphql';
const StyledQueueButtonsRow = styled.div`
display: flex;
flex-wrap: wrap;
gap: ${({ theme }) => theme.spacing(2)};
margin-top: ${({ theme }) => theme.spacing(6)};
`;
const StyledQueueHealthButton = styled(Button)<{
isSelected?: boolean;
status: AdminPanelHealthServiceStatus;
}>`
${({ isSelected, theme, status }) =>
isSelected &&
`
background-color: ${
status === AdminPanelHealthServiceStatus.OPERATIONAL
? theme.tag.background.green
: theme.tag.background.red
};
`}
`;
export const SettingsAdminQueueHealthButtons = ({
queues,
selectedQueue,
toggleQueueVisibility,
}: {
queues: AdminPanelWorkerQueueHealth[];
selectedQueue: string | null;
toggleQueueVisibility: (queueName: string) => void;
}) => {
return (
<StyledQueueButtonsRow>
{queues.map((queue) => (
<StyledQueueHealthButton
key={queue.name}
onClick={() => toggleQueueVisibility(queue.name)}
title={queue.name}
variant="secondary"
isSelected={selectedQueue === queue.name}
status={queue.status}
/>
))}
</StyledQueueButtonsRow>
);
};

View File

@ -1,8 +1,8 @@
import { SettingsAdminEnvVariables } from '@/settings/admin-panel/components/SettingsAdminEnvVariables';
import { SettingsAdminGeneral } from '@/settings/admin-panel/components/SettingsAdminGeneral';
import { SettingsAdminHealthStatus } from '@/settings/admin-panel/components/SettingsAdminHealthStatus';
import { SETTINGS_ADMIN_TABS } from '@/settings/admin-panel/constants/SettingsAdminTabs';
import { SETTINGS_ADMIN_TABS_ID } from '@/settings/admin-panel/constants/SettingsAdminTabsId';
import { SettingsAdminHealthStatus } from '@/settings/admin-panel/health-status/components/SettingsAdminHealthStatus';
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
export const SettingsAdminTabContent = () => {

View File

@ -1,43 +0,0 @@
import { AdminHealthService } from '@/settings/admin-panel/types/AdminHealthService';
import styled from '@emotion/styled';
import { SettingsPath } from '@/types/SettingsPath';
import { Link } from 'react-router-dom';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { SettingsListCard } from '../../components/SettingsListCard';
import { SettingsAdminHealthStatusRightContainer } from './SettingsAdminHealthStatusRightContainer';
const StyledLink = styled(Link)`
text-decoration: none;
`;
export const SettingsHealthStatusListCard = ({
services,
loading,
}: {
services: Array<AdminHealthService>;
loading?: boolean;
}) => {
return (
<>
{services.map((service) => (
<>
<StyledLink
to={getSettingsPath(SettingsPath.AdminPanelIndicatorHealthStatus, {
indicatorName: service.id,
})}
>
<SettingsListCard
items={[service]}
getItemLabel={(service) => service.name}
isLoading={loading}
RowRightComponent={({ item: service }) => (
<SettingsAdminHealthStatusRightContainer service={service} />
)}
/>
</StyledLink>
</>
))}
</>
);
};