You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by "aarochuk (via GitHub)" <gi...@apache.org> on 2025/07/01 16:05:08 UTC

[PR] Add button to download task logs as a text file [airflow]

aarochuk opened a new pull request, #49412:
URL: https://github.com/apache/airflow/pull/49412

   <!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at
   
      http://www.apache.org/licenses/LICENSE-2.0
   
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
    -->
   
   <!--
   Thank you for contributing! Please make sure that your code changes
   are covered with tests. And in case of new features or big changes
   remember to adjust the documentation.
   
   Feel free to ping committers for the review!
   
   In case of an existing issue, reference it using one of the following:
   
   closes: #ISSUE
   related: #ISSUE
   
   How to write a good git commit message:
   http://chris.beams.io/posts/git-commit/
   -->
   
   
   
   <!-- Please keep an empty line above the dashes. -->
   Added ability to download task instance logs in airflow 3 ui as described in issue #47689
   closes: #47689
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-2855900584

   @aarochuk mind rebasing and addressing PR comments?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Issue #47689 Implementation [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on code in PR #49412:
URL: https://github.com/apache/airflow/pull/49412#discussion_r2050740382


##########
airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx:
##########
@@ -83,9 +79,33 @@ export const Logs = () => {
     tryNumber: tryNumber === 0 ? 1 : tryNumber,
   });
 
+  const { datum } = useLogDownload({
+    dagId,
+    logLevelFilters,
+    sourceFilters,
+    taskInstance,
+    tryNumber: tryNumber === 0 ? 1 : tryNumber,
+  });
+
+  const downloadLog = () => {
+    const texts = datum as Array<BlobPart>;
+    const file = new Blob(texts, { type: "text/plain" });
+    const element = document.createElement("a");
+
+    element.href = URL.createObjectURL(file);
+    element.download = `taskInstanceLogs.txt`;

Review Comment:
   +1 on `${dagId}-${taskId}-${runId}-${tryNumber}.txt` 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] closed pull request #49412: Add button to download task logs as a text file
URL: https://github.com/apache/airflow/pull/49412


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "aarochuk (via GitHub)" <gi...@apache.org>.
aarochuk commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-2858945040

   @bbovenzi I will make sure to make another push by the end of the week sorry it has taken so long


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "uranusjr (via GitHub)" <gi...@apache.org>.
uranusjr commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-3183436245

   Removing from 3.1.0 due to lack of response and the PR not in a working state. Please comment if anyone is interested in picking this up, we can add it back if possible.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "phanikumv (via GitHub)" <gi...@apache.org>.
phanikumv commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-3139194912

   @aarochuk just checking in to see if you need help with this PR? 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-3024649761

   @aarochuk are you still able to finish this PR?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-2993835757

   This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Issue #47689 Implementation [airflow]

Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on code in PR #49412:
URL: https://github.com/apache/airflow/pull/49412#discussion_r2050740382


##########
airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx:
##########
@@ -83,9 +79,33 @@ export const Logs = () => {
     tryNumber: tryNumber === 0 ? 1 : tryNumber,
   });
 
+  const { datum } = useLogDownload({
+    dagId,
+    logLevelFilters,
+    sourceFilters,
+    taskInstance,
+    tryNumber: tryNumber === 0 ? 1 : tryNumber,
+  });
+
+  const downloadLog = () => {
+    const texts = datum as Array<BlobPart>;
+    const file = new Blob(texts, { type: "text/plain" });
+    const element = document.createElement("a");
+
+    element.href = URL.createObjectURL(file);
+    element.download = `taskInstanceLogs.txt`;

Review Comment:
   +1 on `${dagId}-${taskId}-${runId}-${mapIndex}-${tryNumber}.txt` 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Issue #47689 Implementation [airflow]

Posted by "tirkarthi (via GitHub)" <gi...@apache.org>.
tirkarthi commented on code in PR #49412:
URL: https://github.com/apache/airflow/pull/49412#discussion_r2049310825


##########
airflow-core/src/airflow/ui/src/queries/useLogs.tsx:
##########
@@ -155,3 +155,138 @@ export const useLogs = (
 
   return { data: parsedData, ...rest };
 };
+
+type LineObject = {
+  props?: Props;
+};
+
+const logDateTime = (line: string): string | undefined => {
+  if (!line || typeof line !== "object") {
+    return undefined;
+  }
+
+  const lineObj = line as LineObject;
+
+  if (!lineObj.props || !("children" in lineObj.props)) {
+    return undefined;
+  }
+
+  const { children } = lineObj.props;
+
+  if (!Array.isArray(children) || children.length <= 2) {
+    return undefined;
+  }
+
+  const { 2: thirdChild } = children;
+
+  const thirdChildObj = thirdChild as { props?: { datetime?: string } };
+
+  if (!thirdChildObj.props || typeof thirdChildObj.props.datetime !== "string") {
+    return undefined;
+  }
+
+  const datetimeStr = thirdChildObj.props.datetime;
+  const date = new Date(datetimeStr);
+
+  if (isNaN(date.getTime())) {
+    return undefined;
+  }
+
+  const year = date.getFullYear();
+  const month = date.getMonth() + 1;
+  const day = date.getDate();
+  const hours = date.getHours();
+  const minutes = date.getMinutes();
+  const seconds = date.getSeconds();
+  const formattedDate = `${year}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`;
+  const formattedTime = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
+
+  return `${formattedDate}, ${formattedTime}`;
+};
+
+const logText = ({ data, logLevelFilters, sourceFilters, taskInstance, tryNumber }: ParseLogsProps) => {
+  let warning;
+  let parsedLines;
+  const sources: Array<string> = [];
+  const logLink = taskInstance ? `${getTaskInstanceLink(taskInstance)}?try_number=${tryNumber}` : "";
+  const elements: Array<string> = [];
+
+  try {
+    parsedLines = data.map((datum, index) => {
+      if (typeof datum !== "string" && "logger" in datum) {
+        const source = datum.logger as string;
+
+        if (!sources.includes(source)) {
+          sources.push(source);
+        }
+      }
+
+      return renderStructuredLog({ index, logLevelFilters, logLink, logMessage: datum, sourceFilters });
+    });
+  } catch (error) {
+    const errorMessage = error instanceof Error ? error.message : "An error occurred.";
+
+    console.warn(`Error parsing logs: ${errorMessage}`);
+    warning = "Unable to show logs. There was an error parsing logs.";
+
+    return { data, warning };
+  }
+  parsedLines.map((line) => {
+    const text = innerText(line);
+
+    if (text !== "") {
+      const datetime = logDateTime(line as string);
+
+      if (datetime === undefined) {
+        elements.push(`${text}\n`);
+      } else {
+        const first = text.slice(0, Math.max(0, text.indexOf("[")));
+        const second = text.slice(Math.max(0, text.indexOf("[") + 1));
+        const newtext = `${first}[${datetime}${second}`;
+
+        elements.push(`${newtext}\n`);
+      }
+    }
+
+    return text;
+  });
+
+  return elements;
+};
+
+export const useLogDownload = (
+  { dagId, logLevelFilters, sourceFilters, taskInstance, tryNumber = 1 }: Props,
+  options?: Omit<UseQueryOptions<TaskInstancesLogResponse>, "queryFn" | "queryKey">,
+) => {
+  const refetchInterval = useAutoRefresh({ dagId });
+
+  const { data, ...rest } = useTaskInstanceServiceGetLog(

Review Comment:
   I guess you can pass `text/plain` in the accept here and get the raw value of the log file in the storage which is the value users usually want to reduce the code for formatting.
   
   `accept?: "application/json" | "text/plain" | "*/*";`
   
   https://github.com/apache/airflow/blob/96c6daa97c94b20b14ec5fa7f39de26b3f2d2559/airflow-core/src/airflow/api_fastapi/core_api/routes/public/log.py#L136-L153



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Issue #47689 Implementation [airflow]

Posted by "tirkarthi (via GitHub)" <gi...@apache.org>.
tirkarthi commented on code in PR #49412:
URL: https://github.com/apache/airflow/pull/49412#discussion_r2049304138


##########
airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx:
##########
@@ -83,9 +79,33 @@ export const Logs = () => {
     tryNumber: tryNumber === 0 ? 1 : tryNumber,
   });
 
+  const { datum } = useLogDownload({
+    dagId,
+    logLevelFilters,
+    sourceFilters,
+    taskInstance,
+    tryNumber: tryNumber === 0 ? 1 : tryNumber,
+  });
+
+  const downloadLog = () => {
+    const texts = datum as Array<BlobPart>;
+    const file = new Blob(texts, { type: "text/plain" });
+    const element = document.createElement("a");
+
+    element.href = URL.createObjectURL(file);
+    element.download = `taskInstanceLogs.txt`;

Review Comment:
   This looks the filename for the downloaded log file. This should include dagId and taskInstance details in the name like Airflow 2 else this might keep overwriting the file on disk or create something like `taskInstanceLogs(1).txt`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Add button to download task logs as a text file [airflow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #49412:
URL: https://github.com/apache/airflow/pull/49412#issuecomment-3387847864

   This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org