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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]