mirror of
https://github.com/datahub-project/datahub.git
synced 2025-09-04 06:43:16 +00:00
feat(frontend/ingestion): Support flagged / warning / connection failure statuses; add recipe (#8920)
This commit is contained in:
parent
bd5c4e0d70
commit
b3ac42b1e4
@ -2,6 +2,7 @@ import { DownloadOutlined } from '@ant-design/icons';
|
|||||||
import { Button, message, Modal, Typography } from 'antd';
|
import { Button, message, Modal, Typography } from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import YAML from 'yamljs';
|
||||||
import { useGetIngestionExecutionRequestQuery } from '../../../../graphql/ingestion.generated';
|
import { useGetIngestionExecutionRequestQuery } from '../../../../graphql/ingestion.generated';
|
||||||
import { ANTD_GRAY } from '../../../entity/shared/constants';
|
import { ANTD_GRAY } from '../../../entity/shared/constants';
|
||||||
import { downloadFile } from '../../../search/utils/csvUtils';
|
import { downloadFile } from '../../../search/utils/csvUtils';
|
||||||
@ -65,6 +66,13 @@ const IngestedAssetsSection = styled.div`
|
|||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const RecipeSection = styled.div`
|
||||||
|
border-top: 1px solid ${ANTD_GRAY[4]};
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
`;
|
||||||
|
|
||||||
const LogsSection = styled.div`
|
const LogsSection = styled.div`
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
@ -91,6 +99,8 @@ type Props = {
|
|||||||
|
|
||||||
export const ExecutionDetailsModal = ({ urn, visible, onClose }: Props) => {
|
export const ExecutionDetailsModal = ({ urn, visible, onClose }: Props) => {
|
||||||
const [showExpandedLogs, setShowExpandedLogs] = useState(false);
|
const [showExpandedLogs, setShowExpandedLogs] = useState(false);
|
||||||
|
const [showExpandedRecipe, setShowExpandedRecipe] = useState(false);
|
||||||
|
|
||||||
const { data, loading, error, refetch } = useGetIngestionExecutionRequestQuery({ variables: { urn } });
|
const { data, loading, error, refetch } = useGetIngestionExecutionRequestQuery({ variables: { urn } });
|
||||||
const output = data?.executionRequest?.result?.report || 'No output found.';
|
const output = data?.executionRequest?.result?.report || 'No output found.';
|
||||||
|
|
||||||
@ -120,7 +130,18 @@ export const ExecutionDetailsModal = ({ urn, visible, onClose }: Props) => {
|
|||||||
const resultSummaryText =
|
const resultSummaryText =
|
||||||
(result && <Typography.Text type="secondary">{getExecutionRequestSummaryText(result)}</Typography.Text>) ||
|
(result && <Typography.Text type="secondary">{getExecutionRequestSummaryText(result)}</Typography.Text>) ||
|
||||||
undefined;
|
undefined;
|
||||||
const isOutputExpandable = output.length > 100;
|
|
||||||
|
const recipeJson = data?.executionRequest?.input.arguments?.find((arg) => arg.key === 'recipe')?.value;
|
||||||
|
let recipeYaml: string;
|
||||||
|
try {
|
||||||
|
recipeYaml = recipeJson && YAML.stringify(JSON.parse(recipeJson), 8, 2).trim();
|
||||||
|
} catch (e) {
|
||||||
|
recipeYaml = '';
|
||||||
|
}
|
||||||
|
const recipe = showExpandedRecipe ? recipeYaml : recipeYaml?.split('\n').slice(0, 1).join('\n');
|
||||||
|
|
||||||
|
const areLogsExpandable = output.length > 100;
|
||||||
|
const isRecipeExpandable = recipeYaml?.includes('\n');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -161,14 +182,32 @@ export const ExecutionDetailsModal = ({ urn, visible, onClose }: Props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</SectionSubHeader>
|
</SectionSubHeader>
|
||||||
<Typography.Paragraph ellipsis>
|
<Typography.Paragraph ellipsis>
|
||||||
<pre>{`${logs}${!showExpandedLogs && isOutputExpandable ? '...' : ''}`}</pre>
|
<pre>{`${logs}${!showExpandedLogs && areLogsExpandable ? '...' : ''}`}</pre>
|
||||||
{isOutputExpandable && (
|
{areLogsExpandable && (
|
||||||
<ShowMoreButton type="link" onClick={() => setShowExpandedLogs(!showExpandedLogs)}>
|
<ShowMoreButton type="link" onClick={() => setShowExpandedLogs(!showExpandedLogs)}>
|
||||||
{showExpandedLogs ? 'Hide' : 'Show More'}
|
{showExpandedLogs ? 'Hide' : 'Show More'}
|
||||||
</ShowMoreButton>
|
</ShowMoreButton>
|
||||||
)}
|
)}
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</LogsSection>
|
</LogsSection>
|
||||||
|
{recipe && (
|
||||||
|
<RecipeSection>
|
||||||
|
<SectionHeader level={5}>Recipe</SectionHeader>
|
||||||
|
<SectionSubHeader>
|
||||||
|
<SubHeaderParagraph type="secondary">
|
||||||
|
The recipe used for this ingestion run.
|
||||||
|
</SubHeaderParagraph>
|
||||||
|
</SectionSubHeader>
|
||||||
|
<Typography.Paragraph ellipsis>
|
||||||
|
<pre>{`${recipe}${!showExpandedRecipe && isRecipeExpandable ? '\n...' : ''}`}</pre>
|
||||||
|
</Typography.Paragraph>
|
||||||
|
{isRecipeExpandable && (
|
||||||
|
<ShowMoreButton type="link" onClick={() => setShowExpandedRecipe((v) => !v)}>
|
||||||
|
{showExpandedRecipe ? 'Hide' : 'Show More'}
|
||||||
|
</ShowMoreButton>
|
||||||
|
)}
|
||||||
|
</RecipeSection>
|
||||||
|
)}
|
||||||
</Section>
|
</Section>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import YAML from 'yamljs';
|
|
||||||
import {
|
import {
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
CloseCircleOutlined,
|
CloseCircleOutlined,
|
||||||
|
ExclamationCircleOutlined,
|
||||||
LoadingOutlined,
|
LoadingOutlined,
|
||||||
|
StopOutlined,
|
||||||
WarningOutlined,
|
WarningOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { ANTD_GRAY, REDESIGN_COLORS } from '../../entity/shared/constants';
|
import YAML from 'yamljs';
|
||||||
import { EntityType, FacetMetadata } from '../../../types.generated';
|
|
||||||
import { capitalizeFirstLetterOnly, pluralize } from '../../shared/textUtil';
|
|
||||||
import EntityRegistry from '../../entity/EntityRegistry';
|
|
||||||
import { SourceConfig } from './builder/types';
|
|
||||||
import { ListIngestionSourcesDocument, ListIngestionSourcesQuery } from '../../../graphql/ingestion.generated';
|
import { ListIngestionSourcesDocument, ListIngestionSourcesQuery } from '../../../graphql/ingestion.generated';
|
||||||
|
import { EntityType, FacetMetadata } from '../../../types.generated';
|
||||||
|
import EntityRegistry from '../../entity/EntityRegistry';
|
||||||
|
import { ANTD_GRAY, REDESIGN_COLORS } from '../../entity/shared/constants';
|
||||||
|
import { capitalizeFirstLetterOnly, pluralize } from '../../shared/textUtil';
|
||||||
|
import { SourceConfig } from './builder/types';
|
||||||
|
|
||||||
export const getSourceConfigs = (ingestionSources: SourceConfig[], sourceType: string) => {
|
export const getSourceConfigs = (ingestionSources: SourceConfig[], sourceType: string) => {
|
||||||
const sourceConfigs = ingestionSources.find((source) => source.name === sourceType);
|
const sourceConfigs = ingestionSources.find((source) => source.name === sourceType);
|
||||||
@ -40,7 +42,9 @@ export function getPlaceholderRecipe(ingestionSources: SourceConfig[], type?: st
|
|||||||
|
|
||||||
export const RUNNING = 'RUNNING';
|
export const RUNNING = 'RUNNING';
|
||||||
export const SUCCESS = 'SUCCESS';
|
export const SUCCESS = 'SUCCESS';
|
||||||
|
export const WARNING = 'WARNING';
|
||||||
export const FAILURE = 'FAILURE';
|
export const FAILURE = 'FAILURE';
|
||||||
|
export const CONNECTION_FAILURE = 'CONNECTION_FAILURE';
|
||||||
export const CANCELLED = 'CANCELLED';
|
export const CANCELLED = 'CANCELLED';
|
||||||
export const UP_FOR_RETRY = 'UP_FOR_RETRY';
|
export const UP_FOR_RETRY = 'UP_FOR_RETRY';
|
||||||
export const ROLLING_BACK = 'ROLLING_BACK';
|
export const ROLLING_BACK = 'ROLLING_BACK';
|
||||||
@ -56,8 +60,10 @@ export const getExecutionRequestStatusIcon = (status: string) => {
|
|||||||
return (
|
return (
|
||||||
(status === RUNNING && LoadingOutlined) ||
|
(status === RUNNING && LoadingOutlined) ||
|
||||||
(status === SUCCESS && CheckCircleOutlined) ||
|
(status === SUCCESS && CheckCircleOutlined) ||
|
||||||
|
(status === WARNING && ExclamationCircleOutlined) ||
|
||||||
(status === FAILURE && CloseCircleOutlined) ||
|
(status === FAILURE && CloseCircleOutlined) ||
|
||||||
(status === CANCELLED && CloseCircleOutlined) ||
|
(status === CONNECTION_FAILURE && CloseCircleOutlined) ||
|
||||||
|
(status === CANCELLED && StopOutlined) ||
|
||||||
(status === UP_FOR_RETRY && ClockCircleOutlined) ||
|
(status === UP_FOR_RETRY && ClockCircleOutlined) ||
|
||||||
(status === ROLLED_BACK && WarningOutlined) ||
|
(status === ROLLED_BACK && WarningOutlined) ||
|
||||||
(status === ROLLING_BACK && LoadingOutlined) ||
|
(status === ROLLING_BACK && LoadingOutlined) ||
|
||||||
@ -70,7 +76,9 @@ export const getExecutionRequestStatusDisplayText = (status: string) => {
|
|||||||
return (
|
return (
|
||||||
(status === RUNNING && 'Running') ||
|
(status === RUNNING && 'Running') ||
|
||||||
(status === SUCCESS && 'Succeeded') ||
|
(status === SUCCESS && 'Succeeded') ||
|
||||||
|
(status === WARNING && 'Completed') ||
|
||||||
(status === FAILURE && 'Failed') ||
|
(status === FAILURE && 'Failed') ||
|
||||||
|
(status === CONNECTION_FAILURE && 'Connection Failed') ||
|
||||||
(status === CANCELLED && 'Cancelled') ||
|
(status === CANCELLED && 'Cancelled') ||
|
||||||
(status === UP_FOR_RETRY && 'Up for Retry') ||
|
(status === UP_FOR_RETRY && 'Up for Retry') ||
|
||||||
(status === ROLLED_BACK && 'Rolled Back') ||
|
(status === ROLLED_BACK && 'Rolled Back') ||
|
||||||
@ -83,21 +91,25 @@ export const getExecutionRequestStatusDisplayText = (status: string) => {
|
|||||||
export const getExecutionRequestSummaryText = (status: string) => {
|
export const getExecutionRequestSummaryText = (status: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case RUNNING:
|
case RUNNING:
|
||||||
return 'Ingestion is running';
|
return 'Ingestion is running...';
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
return 'Ingestion successfully completed';
|
return 'Ingestion succeeded with no errors or suspected missing data.';
|
||||||
|
case WARNING:
|
||||||
|
return 'Ingestion completed with minor or intermittent errors.';
|
||||||
case FAILURE:
|
case FAILURE:
|
||||||
return 'Ingestion completed with errors';
|
return 'Ingestion failed to complete, or completed with serious errors.';
|
||||||
|
case CONNECTION_FAILURE:
|
||||||
|
return 'Ingestion failed due to network, authentication, or permission issues.';
|
||||||
case CANCELLED:
|
case CANCELLED:
|
||||||
return 'Ingestion was cancelled';
|
return 'Ingestion was cancelled.';
|
||||||
case ROLLED_BACK:
|
case ROLLED_BACK:
|
||||||
return 'Ingestion was rolled back';
|
return 'Ingestion was rolled back.';
|
||||||
case ROLLING_BACK:
|
case ROLLING_BACK:
|
||||||
return 'Ingestion is in the process of rolling back';
|
return 'Ingestion is in the process of rolling back.';
|
||||||
case ROLLBACK_FAILED:
|
case ROLLBACK_FAILED:
|
||||||
return 'Ingestion rollback failed';
|
return 'Ingestion rollback failed.';
|
||||||
default:
|
default:
|
||||||
return 'Ingestion status not recognized';
|
return 'Ingestion status not recognized.';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,7 +117,9 @@ export const getExecutionRequestStatusDisplayColor = (status: string) => {
|
|||||||
return (
|
return (
|
||||||
(status === RUNNING && REDESIGN_COLORS.BLUE) ||
|
(status === RUNNING && REDESIGN_COLORS.BLUE) ||
|
||||||
(status === SUCCESS && 'green') ||
|
(status === SUCCESS && 'green') ||
|
||||||
|
(status === WARNING && 'orangered') ||
|
||||||
(status === FAILURE && 'red') ||
|
(status === FAILURE && 'red') ||
|
||||||
|
(status === CONNECTION_FAILURE && 'crimson') ||
|
||||||
(status === UP_FOR_RETRY && 'orange') ||
|
(status === UP_FOR_RETRY && 'orange') ||
|
||||||
(status === CANCELLED && ANTD_GRAY[9]) ||
|
(status === CANCELLED && ANTD_GRAY[9]) ||
|
||||||
(status === ROLLED_BACK && 'orange') ||
|
(status === ROLLED_BACK && 'orange') ||
|
||||||
|
@ -90,6 +90,10 @@ query getIngestionExecutionRequest($urn: String!) {
|
|||||||
source {
|
source {
|
||||||
type
|
type
|
||||||
}
|
}
|
||||||
|
arguments {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result {
|
result {
|
||||||
status
|
status
|
||||||
|
Loading…
x
Reference in New Issue
Block a user