Skip to content

Commit 41c977e

Browse files
committed
feat(FR-532): display error_data of model service's route (#3173)
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
1 parent e6a375f commit 41c977e

25 files changed

+212
-85
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useThemeMode } from '../hooks/useThemeMode';
2+
import BAICodeEditor from './BAICodeEditor';
3+
import BAIModal, { BAIModalProps } from './BAIModal';
4+
import Flex from './Flex';
5+
import { Alert } from 'antd';
6+
import React, { useMemo } from 'react';
7+
import { useTranslation } from 'react-i18next';
8+
9+
interface BAIJSONViewerModalProps extends Omit<BAIModalProps, 'children'> {
10+
json?: object | string;
11+
description?: React.ReactNode;
12+
}
13+
14+
const BAIJSONViewerModal: React.FC<BAIJSONViewerModalProps> = ({
15+
json,
16+
description,
17+
...modalProps
18+
}) => {
19+
const { t } = useTranslation();
20+
const { isDarkMode } = useThemeMode();
21+
22+
const { formattedJson, hasError } = useMemo(() => {
23+
if (typeof json === 'string') {
24+
try {
25+
return {
26+
formattedJson: JSON.stringify(JSON.parse(json), null, 2),
27+
hasError: false,
28+
};
29+
} catch (e) {
30+
return {
31+
formattedJson: json,
32+
hasError: true,
33+
};
34+
}
35+
}
36+
return {
37+
formattedJson: JSON.stringify(json, null, 2),
38+
hasError: false,
39+
};
40+
}, [json]);
41+
42+
return (
43+
<BAIModal footer={null} width={800} {...modalProps}>
44+
<Flex direction="column" align="stretch" gap={'sm'}>
45+
{hasError && (
46+
<Alert
47+
type="warning"
48+
message={t('general.InvalidJSONFormat')}
49+
showIcon
50+
/>
51+
)}
52+
{description}
53+
<BAICodeEditor
54+
value={formattedJson}
55+
language={'json'}
56+
theme={isDarkMode ? 'dark' : 'light'}
57+
editable={false}
58+
/>
59+
</Flex>
60+
</BAIModal>
61+
);
62+
};
63+
64+
export default BAIJSONViewerModal;

react/src/components/InferenceSessionErrorModal.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ const InferenceSessionErrorModal: React.FC<Props> = ({
3232
inferenceSessionErrorFrgmt,
3333
);
3434

35-
// const { errors } = endpoint
36-
// const targetSession = errors.filter(({ session_id }) => session === session_id)
37-
// if (targetSession.length > 0) {
38-
// // setErrorJSONModalSessionID(session)
39-
// // setErrorJSONModalError(targetSession[0].errors[0].repr)
40-
// // setShowErrorJSONModal(true)
41-
// }
42-
4335
const columnSetting: DescriptionsProps['column'] = {
4436
xxl: 1,
4537
xl: 1,

react/src/components/ServiceLauncherPageContent.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,12 @@ const ServiceLauncherPageContent: React.FC<ServiceLauncherPageContentProps> = ({
280280

281281
const mutationToCreateService = useTanMutation<
282282
unknown,
283-
{
284-
message?: string;
285-
},
283+
| {
284+
message?: string;
285+
title?: string;
286+
description?: string;
287+
}
288+
| undefined,
286289
ServiceLauncherFormValue
287290
>({
288291
mutationFn: (values) => {
@@ -582,7 +585,6 @@ const ServiceLauncherPageContent: React.FC<ServiceLauncherPageContentProps> = ({
582585
webuiNavigate(`/serving/${endpoint?.endpoint_id}`);
583586
},
584587
onError: (error) => {
585-
console.log(error);
586588
message.error(t('modelService.FailedToUpdateService'));
587589
},
588590
});

react/src/pages/EndpointDetailPage.tsx

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import AutoScalingRuleEditorModal, {
22
COMPARATOR_LABELS,
33
} from '../components/AutoScalingRuleEditorModal';
4+
import BAIJSONViewerModal from '../components/BAIJSONViewerModal';
45
import CopyableCodeText from '../components/CopyableCodeText';
56
import EndpointOwnerInfo from '../components/EndpointOwnerInfo';
67
import EndpointStatusTag from '../components/EndpointStatusTag';
@@ -35,10 +36,10 @@ import {
3536
CheckOutlined,
3637
CloseOutlined,
3738
DeleteOutlined,
39+
ExclamationCircleOutlined,
3840
FolderOutlined,
3941
LoadingOutlined,
4042
PlusOutlined,
41-
QuestionCircleOutlined,
4243
ReloadOutlined,
4344
SettingOutlined,
4445
SyncOutlined,
@@ -128,6 +129,8 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
128129
const [selectedSessionId, setSelectedSessionId] = useState<string>();
129130
const isSupportAutoScalingRule =
130131
baiClient.isManagerVersionCompatibleWith('25.1.0');
132+
133+
const [errorDataForJSONModal, setErrorDataForJSONModal] = useState<string>();
131134
const { endpoint, endpoint_token_list, endpoint_auto_scaling_rules } =
132135
useLazyLoadQuery<EndpointDetailPageQuery>(
133136
graphql`
@@ -201,6 +204,7 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
201204
traffic_ratio
202205
endpoint
203206
status
207+
error_data
204208
}
205209
created_user_email @since(version: "23.09.8")
206210
...EndpointOwnerInfoFragment
@@ -305,14 +309,6 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
305309
});
306310
},
307311
});
308-
const openSessionErrorModal = (session: string) => {
309-
if (endpoint === null) return;
310-
const { errors } = endpoint || {};
311-
const firstMatchedSessionError = errors?.find(
312-
({ session_id }) => session === session_id,
313-
);
314-
setSelectedSessionErrorForModal(firstMatchedSessionError || null);
315-
};
316312

317313
const [
318314
commitDeleteAutoScalingRuleMutation,
@@ -964,27 +960,61 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
964960
title: t('modelService.RouteId'),
965961
dataIndex: 'routing_id',
966962
fixed: 'left',
963+
render: (text, row) => (
964+
<Typography.Text ellipsis>
965+
{row.routing_id}
966+
{!_.isEmpty(row.error_data) && (
967+
<Button
968+
size="small"
969+
type="text"
970+
icon={<ExclamationCircleOutlined />}
971+
style={{ color: token.colorError }}
972+
onClick={() => {
973+
setErrorDataForJSONModal(row?.error_data || ' ');
974+
}}
975+
/>
976+
)}
977+
</Typography.Text>
978+
),
967979
},
968980
{
969981
title: t('modelService.SessionId'),
970982
dataIndex: 'session',
971983
render: (sessionId) => {
972-
return baiClient.supports('session-node') ? (
973-
<Typography.Link
974-
onClick={() => {
975-
setSelectedSessionId(sessionId);
976-
}}
977-
>
978-
{sessionId}
979-
</Typography.Link>
980-
) : (
981-
<Typography.Text>{sessionId}</Typography.Text>
984+
const matchedSessionError = endpoint?.errors?.find(
985+
(sessionError) => sessionError.session_id === sessionId,
986+
);
987+
return (
988+
<>
989+
{baiClient.supports('session-node') ? (
990+
<Typography.Link
991+
onClick={() => {
992+
setSelectedSessionId(sessionId);
993+
}}
994+
>
995+
{sessionId}
996+
</Typography.Link>
997+
) : (
998+
<Typography.Text>{sessionId}</Typography.Text>
999+
)}
1000+
{matchedSessionError && (
1001+
<Button
1002+
size="small"
1003+
type="text"
1004+
icon={<ExclamationCircleOutlined />}
1005+
style={{ color: token.colorError }}
1006+
onClick={() => {
1007+
setSelectedSessionErrorForModal(matchedSessionError);
1008+
}}
1009+
/>
1010+
)}
1011+
</>
9821012
);
9831013
},
9841014
},
9851015
{
9861016
title: t('modelService.Status'),
987-
render: (_, row) =>
1017+
render: (text, row) =>
9881018
row.status && (
9891019
<>
9901020
<Tag
@@ -994,17 +1024,6 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
9941024
>
9951025
{row.status.toUpperCase()}
9961026
</Tag>
997-
{row.status === 'FAILED_TO_START' && row.session && (
998-
<Button
999-
size="small"
1000-
type="text"
1001-
icon={<QuestionCircleOutlined />}
1002-
style={{ color: token.colorTextSecondary }}
1003-
onClick={() => {
1004-
row.session && openSessionErrorModal(row.session);
1005-
}}
1006-
/>
1007-
)}
10081027
</>
10091028
),
10101029
},
@@ -1067,6 +1086,14 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
10671086
setSelectedSessionId(undefined);
10681087
}}
10691088
/>
1089+
<BAIJSONViewerModal
1090+
open={!!errorDataForJSONModal}
1091+
title={t('modelService.RouteError')}
1092+
json={errorDataForJSONModal}
1093+
onCancel={() => {
1094+
setErrorDataForJSONModal(undefined);
1095+
}}
1096+
/>
10701097
</Flex>
10711098
);
10721099
};

resources/i18n/de.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@
535535
"MaxValueNotification": "{{name}} muss maximal {{max}} sein",
536536
"TotalItems": "Insgesamt {{Gesamt}} Artikel",
537537
"ExtendLoginSession": "Eine Anmeldesitzung verlängern",
538-
"Cores": "Kerne"
538+
"Cores": "Kerne",
539+
"InvalidJSONFormat": "Ungültiges JSON-Format."
539540
},
540541
"credential": {
541542
"Permission": "Genehmigung",
@@ -1606,7 +1607,8 @@
16061607
"Resources": "Ressourcen",
16071608
"NumberOfReplicas": "Anzahl der Replikate",
16081609
"AutoScalingRules": "Automatische Skalierungsregeln",
1609-
"AddRules": "Fügen Sie Regeln hinzu"
1610+
"AddRules": "Fügen Sie Regeln hinzu",
1611+
"RouteError": "Routenfehler"
16101612
},
16111613
"storageHost": {
16121614
"quotaSettings": {

resources/i18n/el.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@
535535
"MaxValueNotification": "{{name}} πρέπει να είναι το μέγιστο {{max}}",
536536
"TotalItems": "Σύνολο {{total}} στοιχείων",
537537
"ExtendLoginSession": "Επέκταση μιας περιόδου σύνδεσης",
538-
"Cores": "πυρήνες"
538+
"Cores": "πυρήνες",
539+
"InvalidJSONFormat": "Μη έγκυρη μορφή JSON."
539540
},
540541
"credential": {
541542
"Permission": "Αδεια",
@@ -1606,7 +1607,8 @@
16061607
"Resources": "Πόροι",
16071608
"NumberOfReplicas": "Αριθμός αντιγράφων",
16081609
"AutoScalingRules": "Κανόνες αυτόματης κλιμάκωσης",
1609-
"AddRules": "Προσθέστε κανόνες"
1610+
"AddRules": "Προσθέστε κανόνες",
1611+
"RouteError": "Σφάλμα διαδρομής"
16101612
},
16111613
"storageHost": {
16121614
"quotaSettings": {

resources/i18n/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,8 @@
528528
"Resources": "Resources",
529529
"NumberOfReplicas": "Number of replicas",
530530
"AutoScalingRules": "Auto Scaling Rules",
531-
"AddRules": "Add Rules"
531+
"AddRules": "Add Rules",
532+
"RouteError": "Route Error"
532533
},
533534
"button": {
534535
"Cancel": "Cancel",
@@ -664,7 +665,8 @@
664665
"MaxValueNotification": "{{name}} must be maximum {{max}}",
665666
"TotalItems": "Total {{total}} items",
666667
"ExtendLoginSession": "Extend login session",
667-
"Cores": "cores"
668+
"Cores": "cores",
669+
"InvalidJSONFormat": "Invalid JSON format."
668670
},
669671
"credential": {
670672
"Permission": "Permission",

resources/i18n/es.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,8 @@
584584
"MaxValueNotification": "{{name}} debe ser máximo {{max}}",
585585
"TotalItems": "Total {{total}} artículos",
586586
"ExtendLoginSession": "Prolongar una sesión de inicio de sesión",
587-
"Cores": "núcleos"
587+
"Cores": "núcleos",
588+
"InvalidJSONFormat": "Formato JSON no válido."
588589
},
589590
"import": {
590591
"CleanUpImportTask": "Tarea de importación de limpieza...",
@@ -857,7 +858,8 @@
857858
"Resources": "Recursos",
858859
"NumberOfReplicas": "Número de réplicas",
859860
"AutoScalingRules": "Reglas de escala automática",
860-
"AddRules": "Agregar reglas"
861+
"AddRules": "Agregar reglas",
862+
"RouteError": "Error de ruta"
861863
},
862864
"notification": {
863865
"Initializing": "Inicializando...",

resources/i18n/fi.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,8 @@
584584
"MaxValueNotification": "{{name}} on oltava maksimi {{max}}",
585585
"TotalItems": "Yhteensä {{total}} kohteita",
586586
"ExtendLoginSession": "Sisäänkirjautumisistunnon laajentaminen",
587-
"Cores": "ytimet"
587+
"Cores": "ytimet",
588+
"InvalidJSONFormat": "Väärä JSON-muoto."
588589
},
589590
"import": {
590591
"CleanUpImportTask": "Tuontitehtävän siivous...",
@@ -856,7 +857,8 @@
856857
"Resources": "Resurssit",
857858
"NumberOfReplicas": "Kopioiden määrä",
858859
"AutoScalingRules": "Automaattiset skaalaussäännöt",
859-
"AddRules": "Lisää sääntöjä"
860+
"AddRules": "Lisää sääntöjä",
861+
"RouteError": "Reittivirhe"
860862
},
861863
"notification": {
862864
"Initializing": "Aloitetaan...",

resources/i18n/fr.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@
535535
"MaxValueNotification": "{{nom}} doit être maximum {{max}}",
536536
"TotalItems": "Total des éléments {{total}}",
537537
"ExtendLoginSession": "Prolonger une session de connexion",
538-
"Cores": "cœurs"
538+
"Cores": "cœurs",
539+
"InvalidJSONFormat": "Format JSON non valide."
539540
},
540541
"credential": {
541542
"Permission": "Autorisation",
@@ -1658,7 +1659,8 @@
16581659
"Resources": "Ressources",
16591660
"NumberOfReplicas": "Nombre de répliques",
16601661
"AutoScalingRules": "Règles de mise à l'échelle automatique",
1661-
"AddRules": "Ajouter des règles"
1662+
"AddRules": "Ajouter des règles",
1663+
"RouteError": "Erreur d'itinéraire"
16621664
},
16631665
"modelStore": {
16641666
"Description": "Description",

0 commit comments

Comments
 (0)