feat(pipeline-task): 实时展示执行日志
This commit is contained in:
@@ -1,9 +1,17 @@
|
||||
import { gql, useQuery } from "@apollo/client";
|
||||
import { gql, useQuery, useSubscription } from "@apollo/client";
|
||||
import { LinearProgress, makeStyles, Typography } from "@material-ui/core";
|
||||
import { format } from 'date-fns';
|
||||
import React, { FC } from "react";
|
||||
import { format } from "date-fns";
|
||||
import React, { FC, useState } from "react";
|
||||
import { ErrorPage } from "../commons/fallbacks/error-page";
|
||||
import { PipelineTask, PipelineTaskLogs } from "../generated/graphql";
|
||||
import {
|
||||
PipelineTask,
|
||||
PipelineTaskEvent,
|
||||
PipelineTaskLogs,
|
||||
TaskStatuses,
|
||||
} from "../generated/graphql";
|
||||
import { PIPELINE_TASK_EVENT } from "./subscriptions";
|
||||
import { clone, find, propEq } from "ramda";
|
||||
import { PipelineUnits } from '../generated/graphql';
|
||||
|
||||
interface Props {
|
||||
taskId: string;
|
||||
@@ -30,30 +38,111 @@ const PIPELINE_TASK = gql`
|
||||
`;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
},
|
||||
root: {},
|
||||
groupTitle: {
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: "white",
|
||||
fontWeight: 500,
|
||||
borderTop: '1px solid #eee',
|
||||
fontSize: '16px',
|
||||
padding: '12px',
|
||||
marginLeft: '1px',
|
||||
borderTop: "1px solid #eee",
|
||||
fontSize: "16px",
|
||||
padding: "12px",
|
||||
marginLeft: "1px",
|
||||
},
|
||||
logText: {
|
||||
fontFamily: 'Menlo, Monaco, "Courier New", monospace',
|
||||
whiteSpace: 'pre-wrap',
|
||||
border: 'none',
|
||||
margin: '6px 12px',
|
||||
display: "block"
|
||||
whiteSpace: "pre-wrap",
|
||||
border: "none",
|
||||
margin: "6px 12px",
|
||||
display: "block",
|
||||
},
|
||||
}));
|
||||
|
||||
export const PipelineTaskDetail: FC<Props> = ({ taskId }) => {
|
||||
const { data, loading, error } = useQuery<{ pipelineTask: PipelineTask }>(
|
||||
PIPELINE_TASK,
|
||||
const [taskEvents, setTaskEvents] = useState(
|
||||
() => new Array<PipelineTaskEvent>()
|
||||
);
|
||||
const { data, loading, error, client } = useQuery<{
|
||||
pipelineTask: PipelineTask;
|
||||
}>(PIPELINE_TASK, {
|
||||
variables: { taskId },
|
||||
});
|
||||
const task = data?.pipelineTask;
|
||||
useSubscription<{ pipelineTaskEvent: PipelineTaskEvent }>(
|
||||
PIPELINE_TASK_EVENT,
|
||||
{
|
||||
variables: { taskId },
|
||||
onSubscriptionData({ subscriptionData: { data } }) {
|
||||
const event = data?.pipelineTaskEvent;
|
||||
console.log(event);
|
||||
if (event && task) {
|
||||
setTaskEvents((prev) => [...prev, event]);
|
||||
if (event.unit) {
|
||||
// event of running scripts
|
||||
client.cache.modify({
|
||||
id: client.cache.identify(task!),
|
||||
fields: {
|
||||
logs(before: PipelineTaskLogs[]) {
|
||||
before = clone(before);
|
||||
let l = find(propEq("unit", event.unit), before);
|
||||
if (l) {
|
||||
l.logs += event.message;
|
||||
} else {
|
||||
l = {
|
||||
unit: event.unit!,
|
||||
logs: event.message,
|
||||
status: event.status,
|
||||
startedAt: event.emittedAt,
|
||||
endedAt: null,
|
||||
__typename: "PipelineTaskLogs",
|
||||
};
|
||||
before.push(l);
|
||||
}
|
||||
if (event.status === TaskStatuses.Working) {
|
||||
l.startedAt || (l.startedAt = event.emittedAt);
|
||||
}
|
||||
if (
|
||||
[TaskStatuses.Failed, TaskStatuses.Success].includes(
|
||||
event.status
|
||||
)
|
||||
) {
|
||||
l.startedAt && (l.startedAt = event.emittedAt);
|
||||
l.endedAt = event.emittedAt;
|
||||
}
|
||||
l.status = event.status;
|
||||
return before;
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// event of task status change
|
||||
client.cache.modify({
|
||||
id: client.cache.identify(task!),
|
||||
fields: {
|
||||
status() {
|
||||
return event.status;
|
||||
},
|
||||
startedAt(before) {
|
||||
if (event.status === TaskStatuses.Working) {
|
||||
return event.emittedAt;
|
||||
} else {
|
||||
return before;
|
||||
}
|
||||
},
|
||||
endedAt(before) {
|
||||
if (
|
||||
[TaskStatuses.Success, TaskStatuses.Failed].includes(
|
||||
event.status
|
||||
)
|
||||
) {
|
||||
return event.emittedAt;
|
||||
} else {
|
||||
return before;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
const classes = useStyles();
|
||||
@@ -71,8 +160,15 @@ export const PipelineTaskDetail: FC<Props> = ({ taskId }) => {
|
||||
<Typography variant="h4" component="h2">
|
||||
{taskId} detail
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h3">
|
||||
{task?.status}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h3">
|
||||
{task?.startedAt && format(task?.startedAt, "yyyy-MM-dd HH:mm:ss.SSS")}-
|
||||
{task?.endedAt && format(task?.endedAt, "yyyy-MM-dd HH:mm:ss.SSS")}
|
||||
</Typography>
|
||||
|
||||
{data?.pipelineTask.logs.map((logs) => (
|
||||
{task?.logs.map((logs) => (
|
||||
<LogGroup key={logs.unit} logs={logs} />
|
||||
))}
|
||||
</div>
|
||||
@@ -84,7 +180,9 @@ const LogGroup: FC<{ logs: PipelineTaskLogs }> = ({ logs }) => {
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.groupTitle}>
|
||||
{logs.unit} {format(logs.startedAt, 'yyyy-MM-dd HH:mm:ss')} {logs.status}
|
||||
{logs.unit}{" "}
|
||||
{logs.startedAt && format(logs.startedAt, "yyyy-MM-dd HH:mm:ss")}{" "}
|
||||
{logs.endedAt && format(logs.endedAt, "yyyy-MM-dd HH:mm:ss")} {logs.status}
|
||||
</div>
|
||||
<code className={classes.logText}>{logs.logs}</code>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user