Skip to content

Commit

Permalink
Add more task details from rest api (#37394)
Browse files Browse the repository at this point in the history
  • Loading branch information
bbovenzi authored Feb 13, 2024
1 parent 270282f commit 3d35fe6
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 72 deletions.
18 changes: 3 additions & 15 deletions airflow/www/static/js/api/useTaskInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,18 @@
*/

import axios, { AxiosResponse } from "axios";
import type { API, TaskInstance } from "src/types";
import type { API } from "src/types";
import { useQuery } from "react-query";
import { useAutoRefresh } from "src/context/autorefresh";

import { getMetaValue } from "src/utils";
import type { SetOptional } from "type-fest";

/* GridData.TaskInstance and API.TaskInstance are not compatible at the moment.
* Remove this function when changing the api response for grid_data_url to comply
* with API.TaskInstance.
*/
const convertTaskInstance = (ti: API.TaskInstance) =>
({ ...ti, runId: ti.dagRunId } as TaskInstance);

const taskInstanceApi = getMetaValue("task_instance_api");

interface Props
extends SetOptional<API.GetMappedTaskInstanceVariables, "mapIndex"> {
enabled: boolean;
enabled?: boolean;
}

const useTaskInstance = ({
Expand All @@ -61,15 +54,10 @@ const useTaskInstance = ({

return useQuery(
["taskInstance", dagId, dagRunId, taskId, mapIndex],
() =>
axios.get<AxiosResponse, API.TaskInstance>(url, {
headers: { Accept: "text/plain" },
}),
() => axios.get<AxiosResponse, API.TaskInstance>(url),
{
placeholderData: {},
refetchInterval: isRefreshOn && (autoRefreshInterval || 1) * 1000,
enabled,
select: convertTaskInstance,
}
);
};
Expand Down
12 changes: 10 additions & 2 deletions airflow/www/static/js/dag/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,11 @@ const Details = ({
<MarkInstanceAs
taskId={taskId}
runId={runId}
state={instance?.state}
state={
!instance?.state || instance?.state === "none"
? undefined
: instance.state
}
isGroup={isGroup}
isMapped={isMapped}
mapIndex={mapIndex}
Expand Down Expand Up @@ -348,7 +352,11 @@ const Details = ({
mapIndex={mapIndex}
executionDate={run?.executionDate}
tryNumber={instance?.tryNumber}
state={instance?.state}
state={
!instance?.state || instance?.state === "none"
? undefined
: instance.state
}
/>
</TabPanel>
)}
Expand Down
147 changes: 120 additions & 27 deletions airflow/www/static/js/dag/details/taskInstance/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,37 @@
*/

import React from "react";
import { Text, Flex, Table, Tbody, Tr, Td, Divider } from "@chakra-ui/react";
import { Text, Flex, Table, Tbody, Tr, Td, Code } from "@chakra-ui/react";
import { snakeCase } from "lodash";

import { getGroupAndMapSummary } from "src/utils";
import { getDuration, formatDuration } from "src/datetime_utils";
import { SimpleStatus } from "src/dag/StatusBox";
import Time from "src/components/Time";
import { ClipboardText } from "src/components/Clipboard";
import type { Task, TaskInstance, TaskState } from "src/types";
import useTaskInstance from "src/api/useTaskInstance";
import type {
API,
Task,
TaskInstance as GridTaskInstance,
TaskState,
} from "src/types";
import DatasetUpdateEvents from "./DatasetUpdateEvents";

interface Props {
instance: TaskInstance;
gridInstance: GridTaskInstance;
taskInstance?: API.TaskInstance;
group: Task;
dagId: string;
}

const Details = ({ instance, group, dagId }: Props) => {
const Details = ({ gridInstance, taskInstance, group }: Props) => {
const isGroup = !!group.children;
const summary: React.ReactNode[] = [];

const { taskId, runId, startDate, endDate, state, mappedStates, mapIndex } =
instance;
const { taskId, runId, startDate, endDate, state } = gridInstance;

const { isMapped, tooltip, operator, hasOutletDatasets, triggerRule } = group;
const mappedStates = !taskInstance ? gridInstance.mappedStates : undefined;

const { data: apiTI } = useTaskInstance({
dagId,
dagRunId: runId,
taskId,
mapIndex,
enabled: !isGroup && !isMapped,
});
const { isMapped, tooltip, operator, hasOutletDatasets, triggerRule } = group;

const { totalTasks, childTaskMap } = getGroupAndMapSummary({
group,
Expand Down Expand Up @@ -83,37 +80,44 @@ const Details = ({ instance, group, dagId }: Props) => {
state &&
["success", "failed", "upstream_failed", "skipped"].includes(state);
const isOverall = (isMapped || isGroup) && "Overall ";

return (
<Flex flexWrap="wrap" justifyContent="space-between">
{state === "deferred" && (
{!!taskInstance?.trigger && !!taskInstance?.triggererJob && (
<>
<Text as="strong">Triggerer info</Text>
<Divider my={2} />
<Text as="strong" mb={3}>
Triggerer info
</Text>
<Table variant="striped" mb={3}>
<Tbody>
<Tr>
<Td>Trigger class</Td>
<Td>{`${apiTI?.trigger?.classpath}`}</Td>
<Td>{`${taskInstance?.trigger?.classpath}`}</Td>
</Tr>
<Tr>
<Td>Trigger ID</Td>
<Td>{`${taskInstance?.trigger?.id}`}</Td>
</Tr>
<Tr>
<Td>Trigger creation time</Td>
<Td>{`${apiTI?.trigger?.createdDate}`}</Td>
<Td>{`${taskInstance?.trigger?.createdDate}`}</Td>
</Tr>
<Tr>
<Td>Assigned triggerer</Td>
<Td>{`${apiTI?.triggererJob?.hostname}`}</Td>
<Td>{`${taskInstance?.triggererJob?.hostname}`}</Td>
</Tr>
<Tr>
<Td>Latest triggerer heartbeat</Td>
<Td>{`${apiTI?.triggererJob?.latestHeartbeat}`}</Td>
<Td>{`${taskInstance?.triggererJob?.latestHeartbeat}`}</Td>
</Tr>
</Tbody>
</Table>
</>
)}

<Text as="strong">Task Instance Details</Text>
<Divider my={2} />
<Text as="strong" mb={3}>
Task Instance Details
</Text>
<Table variant="striped">
<Tbody>
{tooltip && (
Expand Down Expand Up @@ -167,10 +171,16 @@ const Details = ({ instance, group, dagId }: Props) => {
</Text>
</Td>
</Tr>
{mapIndex !== undefined && (
{taskInstance?.mapIndex !== undefined && (
<Tr>
<Td>Map Index</Td>
<Td>{mapIndex}</Td>
<Td>{taskInstance.mapIndex}</Td>
</Tr>
)}
{!!taskInstance?.tryNumber && (
<Tr>
<Td>Try Number</Td>
<Td>{taskInstance.tryNumber}</Td>
</Tr>
)}
{operator && (
Expand Down Expand Up @@ -210,6 +220,89 @@ const Details = ({ instance, group, dagId }: Props) => {
</Td>
</Tr>
)}
{!!taskInstance?.pid && (
<Tr>
<Td>Process ID (PID)</Td>
<Td>
<ClipboardText value={taskInstance.pid.toString()} />
</Td>
</Tr>
)}
{!!taskInstance?.hostname && (
<Tr>
<Td>Hostname</Td>
<Td>
<ClipboardText value={taskInstance.hostname} />
</Td>
</Tr>
)}
{taskInstance?.renderedFields && (
<>
{Object.keys(taskInstance.renderedFields).map((key) => {
const renderedFields = taskInstance.renderedFields as Record<
string,
unknown
>;
if (renderedFields[key]) {
return (
<Tr key={key}>
<Td>{key}</Td>
<Td>
<Code fontSize="md">
{JSON.stringify(renderedFields[key])}
</Code>
</Td>
</Tr>
);
}
return null;
})}
</>
)}
{!!taskInstance?.pool && (
<Tr>
<Td>Pool</Td>
<Td>{taskInstance.pool}</Td>
</Tr>
)}
{!!taskInstance?.poolSlots && (
<Tr>
<Td>Pool Slots</Td>
<Td>{taskInstance.poolSlots}</Td>
</Tr>
)}
{!!taskInstance?.executorConfig && (
<Tr>
<Td>Executor Config</Td>
<Td>
<Code fontSize="md">{taskInstance.executorConfig}</Code>
</Td>
</Tr>
)}
{!!taskInstance?.unixname && (
<Tr>
<Td>Unix Name</Td>
<Td>{taskInstance.unixname}</Td>
</Tr>
)}
{!!taskInstance?.maxTries && (
<Tr>
<Td>Max Tries</Td>
<Td>{taskInstance.maxTries}</Td>
</Tr>
)}
{!!taskInstance?.queue && (
<Tr>
<Td>Queue</Td>
<Td>{taskInstance.queue}</Td>
</Tr>
)}
{!!taskInstance?.priorityWeight && (
<Tr>
<Td>Priority Weight</Td>
<Td>{taskInstance.priorityWeight}</Td>
</Tr>
)}
</Tbody>
</Table>
{hasOutletDatasets && (
Expand Down
5 changes: 2 additions & 3 deletions airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ const ExtraLinks = ({
url && /^(?:[a-z]+:)?\/\//.test(url);

return (
<Box mb={3}>
<Box my={3}>
<Text as="strong">Extra Links</Text>
<Divider my={2} />
<Flex flexWrap="wrap">
<Flex flexWrap="wrap" mt={3}>
{links.map(({ name, url }) => (
<Button
key={name}
Expand Down
42 changes: 17 additions & 25 deletions airflow/www/static/js/dag/details/taskInstance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Box } from "@chakra-ui/react";

import { useGridData, useTaskInstance } from "src/api";
import { getMetaValue, getTask, useOffsetTop } from "src/utils";
import type { DagRun, TaskInstance as TaskInstanceType } from "src/types";
import type { DagRun, TaskInstance as GridTaskInstance } from "src/types";
import NotesAccordion from "src/dag/details/NotesAccordion";

import TaskNav from "./Nav";
Expand All @@ -34,7 +34,7 @@ const dagId = getMetaValue("dag_id")!;
interface Props {
taskId: string;
runId: DagRun["runId"];
mapIndex: TaskInstanceType["mapIndex"];
mapIndex: GridTaskInstance["mapIndex"];
}

const TaskInstance = ({ taskId, runId, mapIndex }: Props) => {
Expand All @@ -56,19 +56,16 @@ const TaskInstance = ({ taskId, runId, mapIndex }: Props) => {
const isGroup = !!children;
const isGroupOrMappedTaskSummary = isGroup || isMappedTaskSummary;

const { data: mappedTaskInstance } = useTaskInstance({
const { data: taskInstance } = useTaskInstance({
dagId,
dagRunId: runId,
taskId,
mapIndex,
enabled: isMapIndexDefined,
enabled: (!isGroup && !isMapped) || isMapIndexDefined,
});
const gridInstance = group?.instances.find((ti) => ti.runId === runId);

const instance = isMapIndexDefined
? mappedTaskInstance
: group?.instances.find((ti) => ti.runId === runId);

if (!group || !run || !instance) return null;
if (!group || !run || !gridInstance) return null;

const { executionDate } = run;

Expand All @@ -94,31 +91,26 @@ const TaskInstance = ({ taskId, runId, mapIndex }: Props) => {
dagId={dagId}
runId={runId}
taskId={taskId}
mapIndex={instance.mapIndex}
initialValue={instance.note}
key={dagId + runId + taskId + instance.mapIndex}
/>
)}
{isMapped && group.extraLinks && isMapIndexDefined && (
<ExtraLinks
taskId={taskId}
dagId={dagId}
mapIndex={mapIndex}
executionDate={executionDate}
extraLinks={group?.extraLinks}
tryNumber={instance.tryNumber}
mapIndex={gridInstance.mapIndex}
initialValue={gridInstance.note}
key={dagId + runId + taskId + gridInstance.mapIndex}
/>
)}
{!isMapped && group.extraLinks && (
{!!group.extraLinks?.length && !isGroupOrMappedTaskSummary && (
<ExtraLinks
taskId={taskId}
dagId={dagId}
mapIndex={isMapped && isMapIndexDefined ? mapIndex : undefined}
executionDate={executionDate}
extraLinks={group?.extraLinks}
tryNumber={instance.tryNumber}
tryNumber={taskInstance?.tryNumber || gridInstance.tryNumber}
/>
)}
<Details instance={instance} group={group} dagId={dagId} />
<Details
gridInstance={gridInstance}
taskInstance={taskInstance}
group={group}
/>
</Box>
);
};
Expand Down

0 comments on commit 3d35fe6

Please sign in to comment.