This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 3d35fe602c Add more task details from rest api (#37394)
3d35fe602c is described below

commit 3d35fe602ce4c033e47dbe3a4d67f673a14f48d9
Author: Brent Bovenzi <[email protected]>
AuthorDate: Tue Feb 13 15:29:53 2024 -0500

    Add more task details from rest api (#37394)
---
 airflow/www/static/js/api/useTaskInstance.ts       |  18 +--
 airflow/www/static/js/dag/details/index.tsx        |  12 +-
 .../static/js/dag/details/taskInstance/Details.tsx | 147 +++++++++++++++++----
 .../js/dag/details/taskInstance/ExtraLinks.tsx     |   5 +-
 .../static/js/dag/details/taskInstance/index.tsx   |  42 +++---
 5 files changed, 152 insertions(+), 72 deletions(-)

diff --git a/airflow/www/static/js/api/useTaskInstance.ts 
b/airflow/www/static/js/api/useTaskInstance.ts
index 2b2818bc21..84d44ca02d 100644
--- a/airflow/www/static/js/api/useTaskInstance.ts
+++ b/airflow/www/static/js/api/useTaskInstance.ts
@@ -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 = ({
@@ -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,
     }
   );
 };
diff --git a/airflow/www/static/js/dag/details/index.tsx 
b/airflow/www/static/js/dag/details/index.tsx
index 918fa7c804..3b058dab42 100644
--- a/airflow/www/static/js/dag/details/index.tsx
+++ b/airflow/www/static/js/dag/details/index.tsx
@@ -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}
@@ -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>
           )}
diff --git a/airflow/www/static/js/dag/details/taskInstance/Details.tsx 
b/airflow/www/static/js/dag/details/taskInstance/Details.tsx
index 5cf1c5cfb9..2fcbb74a57 100644
--- a/airflow/www/static/js/dag/details/taskInstance/Details.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Details.tsx
@@ -18,7 +18,7 @@
  */
 
 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";
@@ -26,32 +26,29 @@ 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,
@@ -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 && (
@@ -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 && (
@@ -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 && (
diff --git a/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx 
b/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
index a1f88e9623..1cd4c450c3 100644
--- a/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
@@ -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}
diff --git a/airflow/www/static/js/dag/details/taskInstance/index.tsx 
b/airflow/www/static/js/dag/details/taskInstance/index.tsx
index bb5f63fb5b..71f8717dd5 100644
--- a/airflow/www/static/js/dag/details/taskInstance/index.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/index.tsx
@@ -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";
@@ -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) => {
@@ -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;
 
@@ -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>
   );
 };

Reply via email to