Skip to content

Commit

Permalink
feat(FR-532): display error_data of model service's route (#3173)
Browse files Browse the repository at this point in the history
resolves #3179 (FR-532)

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/XqC2uNFuj0wg8I60sMUh/5e2fa753-9c82-4372-9ab4-949115819127.png)

Improves error handling and visualization in the model service UI by:

1. Adding a new JSON viewer modal component for displaying error details

    ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/XqC2uNFuj0wg8I60sMUh/bdf791a0-56ed-46ea-aeef-1e49f8d0aa4f.png)

2. Replacing question mark icons with exclamation icons for error indicators
3. Adding error data visualization for both session and route errors
4. Adding translations for JSON format errors and route errors across all languages
  • Loading branch information
yomybaby committed Feb 17, 2025
1 parent e6a375f commit 41c977e
Show file tree
Hide file tree
Showing 25 changed files with 212 additions and 85 deletions.
64 changes: 64 additions & 0 deletions react/src/components/BAIJSONViewerModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useThemeMode } from '../hooks/useThemeMode';
import BAICodeEditor from './BAICodeEditor';
import BAIModal, { BAIModalProps } from './BAIModal';
import Flex from './Flex';
import { Alert } from 'antd';
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';

interface BAIJSONViewerModalProps extends Omit<BAIModalProps, 'children'> {
json?: object | string;
description?: React.ReactNode;
}

const BAIJSONViewerModal: React.FC<BAIJSONViewerModalProps> = ({
json,
description,
...modalProps
}) => {
const { t } = useTranslation();
const { isDarkMode } = useThemeMode();

const { formattedJson, hasError } = useMemo(() => {
if (typeof json === 'string') {
try {
return {
formattedJson: JSON.stringify(JSON.parse(json), null, 2),
hasError: false,
};
} catch (e) {
return {
formattedJson: json,
hasError: true,
};
}
}
return {
formattedJson: JSON.stringify(json, null, 2),
hasError: false,
};
}, [json]);

return (
<BAIModal footer={null} width={800} {...modalProps}>
<Flex direction="column" align="stretch" gap={'sm'}>
{hasError && (
<Alert
type="warning"
message={t('general.InvalidJSONFormat')}
showIcon
/>
)}
{description}
<BAICodeEditor
value={formattedJson}
language={'json'}
theme={isDarkMode ? 'dark' : 'light'}
editable={false}
/>
</Flex>
</BAIModal>
);
};

export default BAIJSONViewerModal;
8 changes: 0 additions & 8 deletions react/src/components/InferenceSessionErrorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,6 @@ const InferenceSessionErrorModal: React.FC<Props> = ({
inferenceSessionErrorFrgmt,
);

// const { errors } = endpoint
// const targetSession = errors.filter(({ session_id }) => session === session_id)
// if (targetSession.length > 0) {
// // setErrorJSONModalSessionID(session)
// // setErrorJSONModalError(targetSession[0].errors[0].repr)
// // setShowErrorJSONModal(true)
// }

const columnSetting: DescriptionsProps['column'] = {
xxl: 1,
xl: 1,
Expand Down
10 changes: 6 additions & 4 deletions react/src/components/ServiceLauncherPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,12 @@ const ServiceLauncherPageContent: React.FC<ServiceLauncherPageContentProps> = ({

const mutationToCreateService = useTanMutation<
unknown,
{
message?: string;
},
| {
message?: string;
title?: string;
description?: string;
}
| undefined,
ServiceLauncherFormValue
>({
mutationFn: (values) => {
Expand Down Expand Up @@ -582,7 +585,6 @@ const ServiceLauncherPageContent: React.FC<ServiceLauncherPageContentProps> = ({
webuiNavigate(`/serving/${endpoint?.endpoint_id}`);
},
onError: (error) => {
console.log(error);
message.error(t('modelService.FailedToUpdateService'));
},
});
Expand Down
89 changes: 58 additions & 31 deletions react/src/pages/EndpointDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import AutoScalingRuleEditorModal, {
COMPARATOR_LABELS,
} from '../components/AutoScalingRuleEditorModal';
import BAIJSONViewerModal from '../components/BAIJSONViewerModal';
import CopyableCodeText from '../components/CopyableCodeText';
import EndpointOwnerInfo from '../components/EndpointOwnerInfo';
import EndpointStatusTag from '../components/EndpointStatusTag';
Expand Down Expand Up @@ -35,10 +36,10 @@ import {
CheckOutlined,
CloseOutlined,
DeleteOutlined,
ExclamationCircleOutlined,
FolderOutlined,
LoadingOutlined,
PlusOutlined,
QuestionCircleOutlined,
ReloadOutlined,
SettingOutlined,
SyncOutlined,
Expand Down Expand Up @@ -128,6 +129,8 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
const [selectedSessionId, setSelectedSessionId] = useState<string>();
const isSupportAutoScalingRule =
baiClient.isManagerVersionCompatibleWith('25.1.0');

const [errorDataForJSONModal, setErrorDataForJSONModal] = useState<string>();
const { endpoint, endpoint_token_list, endpoint_auto_scaling_rules } =
useLazyLoadQuery<EndpointDetailPageQuery>(
graphql`
Expand Down Expand Up @@ -201,6 +204,7 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
traffic_ratio
endpoint
status
error_data
}
created_user_email @since(version: "23.09.8")
...EndpointOwnerInfoFragment
Expand Down Expand Up @@ -305,14 +309,6 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
});
},
});
const openSessionErrorModal = (session: string) => {
if (endpoint === null) return;
const { errors } = endpoint || {};
const firstMatchedSessionError = errors?.find(
({ session_id }) => session === session_id,
);
setSelectedSessionErrorForModal(firstMatchedSessionError || null);
};

const [
commitDeleteAutoScalingRuleMutation,
Expand Down Expand Up @@ -964,27 +960,61 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
title: t('modelService.RouteId'),
dataIndex: 'routing_id',
fixed: 'left',
render: (text, row) => (
<Typography.Text ellipsis>
{row.routing_id}
{!_.isEmpty(row.error_data) && (
<Button
size="small"
type="text"
icon={<ExclamationCircleOutlined />}
style={{ color: token.colorError }}
onClick={() => {
setErrorDataForJSONModal(row?.error_data || ' ');
}}
/>
)}
</Typography.Text>
),
},
{
title: t('modelService.SessionId'),
dataIndex: 'session',
render: (sessionId) => {
return baiClient.supports('session-node') ? (
<Typography.Link
onClick={() => {
setSelectedSessionId(sessionId);
}}
>
{sessionId}
</Typography.Link>
) : (
<Typography.Text>{sessionId}</Typography.Text>
const matchedSessionError = endpoint?.errors?.find(
(sessionError) => sessionError.session_id === sessionId,
);
return (
<>
{baiClient.supports('session-node') ? (
<Typography.Link
onClick={() => {
setSelectedSessionId(sessionId);
}}
>
{sessionId}
</Typography.Link>
) : (
<Typography.Text>{sessionId}</Typography.Text>
)}
{matchedSessionError && (
<Button
size="small"
type="text"
icon={<ExclamationCircleOutlined />}
style={{ color: token.colorError }}
onClick={() => {
setSelectedSessionErrorForModal(matchedSessionError);
}}
/>
)}
</>
);
},
},
{
title: t('modelService.Status'),
render: (_, row) =>
render: (text, row) =>
row.status && (
<>
<Tag
Expand All @@ -994,17 +1024,6 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
>
{row.status.toUpperCase()}
</Tag>
{row.status === 'FAILED_TO_START' && row.session && (
<Button
size="small"
type="text"
icon={<QuestionCircleOutlined />}
style={{ color: token.colorTextSecondary }}
onClick={() => {
row.session && openSessionErrorModal(row.session);
}}
/>
)}
</>
),
},
Expand Down Expand Up @@ -1067,6 +1086,14 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
setSelectedSessionId(undefined);
}}
/>
<BAIJSONViewerModal
open={!!errorDataForJSONModal}
title={t('modelService.RouteError')}
json={errorDataForJSONModal}
onCancel={() => {
setErrorDataForJSONModal(undefined);
}}
/>
</Flex>
);
};
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,8 @@
"MaxValueNotification": "{{name}} muss maximal {{max}} sein",
"TotalItems": "Insgesamt {{Gesamt}} Artikel",
"ExtendLoginSession": "Eine Anmeldesitzung verlängern",
"Cores": "Kerne"
"Cores": "Kerne",
"InvalidJSONFormat": "Ungültiges JSON-Format."
},
"credential": {
"Permission": "Genehmigung",
Expand Down Expand Up @@ -1606,7 +1607,8 @@
"Resources": "Ressourcen",
"NumberOfReplicas": "Anzahl der Replikate",
"AutoScalingRules": "Automatische Skalierungsregeln",
"AddRules": "Fügen Sie Regeln hinzu"
"AddRules": "Fügen Sie Regeln hinzu",
"RouteError": "Routenfehler"
},
"storageHost": {
"quotaSettings": {
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,8 @@
"MaxValueNotification": "{{name}} πρέπει να είναι το μέγιστο {{max}}",
"TotalItems": "Σύνολο {{total}} στοιχείων",
"ExtendLoginSession": "Επέκταση μιας περιόδου σύνδεσης",
"Cores": "πυρήνες"
"Cores": "πυρήνες",
"InvalidJSONFormat": "Μη έγκυρη μορφή JSON."
},
"credential": {
"Permission": "Αδεια",
Expand Down Expand Up @@ -1606,7 +1607,8 @@
"Resources": "Πόροι",
"NumberOfReplicas": "Αριθμός αντιγράφων",
"AutoScalingRules": "Κανόνες αυτόματης κλιμάκωσης",
"AddRules": "Προσθέστε κανόνες"
"AddRules": "Προσθέστε κανόνες",
"RouteError": "Σφάλμα διαδρομής"
},
"storageHost": {
"quotaSettings": {
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,8 @@
"Resources": "Resources",
"NumberOfReplicas": "Number of replicas",
"AutoScalingRules": "Auto Scaling Rules",
"AddRules": "Add Rules"
"AddRules": "Add Rules",
"RouteError": "Route Error"
},
"button": {
"Cancel": "Cancel",
Expand Down Expand Up @@ -664,7 +665,8 @@
"MaxValueNotification": "{{name}} must be maximum {{max}}",
"TotalItems": "Total {{total}} items",
"ExtendLoginSession": "Extend login session",
"Cores": "cores"
"Cores": "cores",
"InvalidJSONFormat": "Invalid JSON format."
},
"credential": {
"Permission": "Permission",
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@
"MaxValueNotification": "{{name}} debe ser máximo {{max}}",
"TotalItems": "Total {{total}} artículos",
"ExtendLoginSession": "Prolongar una sesión de inicio de sesión",
"Cores": "núcleos"
"Cores": "núcleos",
"InvalidJSONFormat": "Formato JSON no válido."
},
"import": {
"CleanUpImportTask": "Tarea de importación de limpieza...",
Expand Down Expand Up @@ -857,7 +858,8 @@
"Resources": "Recursos",
"NumberOfReplicas": "Número de réplicas",
"AutoScalingRules": "Reglas de escala automática",
"AddRules": "Agregar reglas"
"AddRules": "Agregar reglas",
"RouteError": "Error de ruta"
},
"notification": {
"Initializing": "Inicializando...",
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@
"MaxValueNotification": "{{name}} on oltava maksimi {{max}}",
"TotalItems": "Yhteensä {{total}} kohteita",
"ExtendLoginSession": "Sisäänkirjautumisistunnon laajentaminen",
"Cores": "ytimet"
"Cores": "ytimet",
"InvalidJSONFormat": "Väärä JSON-muoto."
},
"import": {
"CleanUpImportTask": "Tuontitehtävän siivous...",
Expand Down Expand Up @@ -856,7 +857,8 @@
"Resources": "Resurssit",
"NumberOfReplicas": "Kopioiden määrä",
"AutoScalingRules": "Automaattiset skaalaussäännöt",
"AddRules": "Lisää sääntöjä"
"AddRules": "Lisää sääntöjä",
"RouteError": "Reittivirhe"
},
"notification": {
"Initializing": "Aloitetaan...",
Expand Down
6 changes: 4 additions & 2 deletions resources/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,8 @@
"MaxValueNotification": "{{nom}} doit être maximum {{max}}",
"TotalItems": "Total des éléments {{total}}",
"ExtendLoginSession": "Prolonger une session de connexion",
"Cores": "cœurs"
"Cores": "cœurs",
"InvalidJSONFormat": "Format JSON non valide."
},
"credential": {
"Permission": "Autorisation",
Expand Down Expand Up @@ -1658,7 +1659,8 @@
"Resources": "Ressources",
"NumberOfReplicas": "Nombre de répliques",
"AutoScalingRules": "Règles de mise à l'échelle automatique",
"AddRules": "Ajouter des règles"
"AddRules": "Ajouter des règles",
"RouteError": "Erreur d'itinéraire"
},
"modelStore": {
"Description": "Description",
Expand Down
Loading

0 comments on commit 41c977e

Please sign in to comment.