This is an automated email from the ASF dual-hosted git repository.
vatsrahul1001 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 059ceef1230 Move Task Identity line into Pre Execution block in logs
(#67036)
059ceef1230 is described below
commit 059ceef1230d5181e59b0f982893cff521a5d885
Author: Jens Scheffler <[email protected]>
AuthorDate: Mon May 18 18:56:56 2026 +0200
Move Task Identity line into Pre Execution block in logs (#67036)
---
.../src/airflow/ui/src/mocks/handlers/log.ts | 14 +++++++++-
.../ui/src/pages/TaskInstance/Logs/Logs.test.tsx | 17 +++++++-----
.../ui/src/pages/TaskInstance/Logs/utils.test.ts | 7 ++---
.../ui/src/pages/TaskInstance/Logs/utils.ts | 6 ++---
.../src/airflow/ui/src/queries/useLogs.tsx | 31 +++++++++++++---------
5 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/mocks/handlers/log.ts
b/airflow-core/src/airflow/ui/src/mocks/handlers/log.ts
index 2cf2ed177d4..5f6f2eef241 100644
--- a/airflow-core/src/airflow/ui/src/mocks/handlers/log.ts
+++ b/airflow-core/src/airflow/ui/src/mocks/handlers/log.ts
@@ -227,9 +227,21 @@ export const handlers: Array<HttpHandler> = [
timestamp: "2025-02-18T12:19:56.263258Z",
try_number: 1,
},
+ { event: "::group::Pre Execute" },
+ {
+ event: "DAG bundles loaded: dags-folder, example_dags",
+ level: "info",
+ timestamp: "2025-02-18T12:19:56.400000Z",
+ },
+ {
+ event: "Filling up the DagBag from /files/dags/log_grouping.py",
+ level: "info",
+ timestamp: "2025-02-18T12:19:56.400000Z",
+ },
+ { event: "::endgroup::" },
{
dag_id: "log_grouping",
- event: "Task finished",
+ event: "Done. Returned value was: None",
level: "info",
map_index: -1,
run_id: "manual__2025-02-18T12:19",
diff --git
a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.test.tsx
b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.test.tsx
index 8a28bb77b0e..77c051e05c0 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.test.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.test.tsx
@@ -181,7 +181,7 @@ describe("Task log grouping", () => {
});
describe("Task Identity preamble", () => {
- it("renders Task Identity preamble after the Log message source details
group", async () => {
+ it("renders Task Identity preamble after the 'Pre Execute' group header as
first group element", async () => {
render(
<AppWrapper
initialEntries={["/dags/log_grouping/runs/manual__2025-02-18T12:19/tasks/ti_context"]}
/>,
);
@@ -192,22 +192,27 @@ describe("Task Identity preamble", () => {
expect(sourceGroup).toBeInTheDocument();
- // Task Identity preamble should be visible
- expect(screen.getByText("Task Identity")).toBeInTheDocument();
+ // Expand the Pre Execute group to reveal the preamble
+ const groupHeader = screen.getByTestId("summary-Pre Execute");
+
+ fireEvent.click(groupHeader);
+
+ // Task Identity preamble should be visible after expanding the group
+ await waitFor(() => expect(screen.getByText("Task
Identity")).toBeInTheDocument());
expect(screen.getByText("ti_id")).toBeInTheDocument();
// Value is a text node adjacent to =; match via partial text
expect(screen.getByText(/01951900-16f6-7c1c-ae66-91bdfe9e0cfd/u)).toBeInTheDocument();
+ expect(screen.getByText("Done. Returned value was:
None")).toBeInTheDocument();
- // Preamble should come after the source details group in DOM order.
+ // Preamble should come after the "Pre Execute" group header in DOM order.
const preamble = screen.getByText("Task Identity");
- const groupHeader = sourceGroup.closest('[data-testid^="group-header-"]');
expect(preamble).toBeInTheDocument();
expect(groupHeader).toBeInTheDocument();
// DOCUMENT_POSITION_FOLLOWING (4) is set when preamble comes after
groupHeader
// eslint-disable-next-line no-bitwise
- expect(groupHeader!.compareDocumentPosition(preamble) &
Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
+ expect(groupHeader.compareDocumentPosition(preamble) &
Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
});
it("does not render TI context fields on individual log lines", async () => {
diff --git
a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.test.ts
b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.test.ts
index 9d2cf6231df..4ca6a9f2530 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.test.ts
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.test.ts
@@ -44,7 +44,7 @@ describe("getDownloadText", () => {
translate,
};
- it("places Task Identity preamble after the source details endgroup, before
the first log line", () => {
+ it("places Task Identity preamble after the 'Pre Execute' group header,
before the first log line", () => {
const fetchedData = {
content: [
{ event: "::group::Log message source details" },
@@ -52,6 +52,7 @@ describe("getDownloadText", () => {
{ event: "/logs/b.log" },
{ event: "some source detail" },
{ event: "::endgroup::" },
+ tiLine("::group::Pre Execute", "2026-01-01T00:00:00Z"),
tiLine("First log line", "2026-01-01T00:00:00Z"),
tiLine("Second log line", "2026-01-01T00:00:01Z"),
],
@@ -60,10 +61,10 @@ describe("getDownloadText", () => {
const lines = getDownloadText({ ...baseOptions, fetchedData });
const preambleIdx = lines.findIndex((line) => line.includes("Task
Identity"));
- const endGroupIdx = lines.findIndex((line) =>
line.includes("::endgroup::"));
+ const preExecuteGroupIdx = lines.findIndex((line) =>
line.includes("::group::Pre Execute"));
const firstLogIdx = lines.findIndex((line) => line.includes("First log
line"));
- expect(preambleIdx).toBeGreaterThan(endGroupIdx);
+ expect(preambleIdx).toBeGreaterThan(preExecuteGroupIdx);
expect(preambleIdx).toBeLessThan(firstLogIdx);
});
diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.ts
b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.ts
index addde304fdc..424006498ee 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.ts
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/utils.ts
@@ -67,14 +67,14 @@ export const getDownloadText = ({
);
if (tiContext !== undefined) {
- const firstEndGroup = lines.findIndex((line) => {
+ const preExecuteGroup = lines.findIndex((line) => {
const text = typeof line === "string" ? line : line.event;
- return text.includes("::endgroup::");
+ return text.includes("::group::Pre Execute");
});
rendered.splice(
- firstEndGroup === -1 ? 0 : firstEndGroup + 1,
+ preExecuteGroup === -1 ? 0 : preExecuteGroup + 1,
0,
renderTIContextPreamble(tiContext, "text", "Task Identity") as string,
);
diff --git a/airflow-core/src/airflow/ui/src/queries/useLogs.tsx
b/airflow-core/src/airflow/ui/src/queries/useLogs.tsx
index fee26772eab..3d0443c04cd 100644
--- a/airflow-core/src/airflow/ui/src/queries/useLogs.tsx
+++ b/airflow-core/src/airflow/ui/src/queries/useLogs.tsx
@@ -175,31 +175,36 @@ const parseLogs = ({
})();
// Extract TI identity fields from the first structured log line and insert
a single preamble
- // entry after the "Log message source details" group (or at position 0 if
absent), so they
+ // entry after the "Pre Execute" group header (or at position 0 if absent),
so they
// appear once rather than repeated on every line.
const tiContext = extractTIContext(data);
if (tiContext !== undefined) {
let insertAt = 0;
- const sourceDetailsIndex = flatEntries.findIndex(
+ let insertGroup: { id: number; level: number; parentId?: number; type:
"header" | "line" } | undefined =
+ undefined;
+ const preExecuteIndex = flatEntries.findIndex(
(entry) =>
entry.group?.type === "header" &&
typeof entry.element === "string" &&
- entry.element.startsWith("Log message source details"),
+ entry.element.startsWith("Pre Execute"),
);
- const sourceGroup = sourceDetailsIndex === -1 ? undefined :
flatEntries[sourceDetailsIndex];
+ const preExecuteGroup = preExecuteIndex === -1 ? undefined :
flatEntries[preExecuteIndex];
- if (sourceGroup?.group !== undefined) {
- const sourceGroupId = sourceGroup.group.id;
- const lastMemberIndex = flatEntries.reduce(
- (last, entry, idx) => (entry.group?.id === sourceGroupId ? idx : last),
- sourceDetailsIndex,
- );
-
- insertAt = lastMemberIndex + 1;
+ if (preExecuteGroup?.group !== undefined) {
+ insertAt = preExecuteIndex + 1;
+ insertGroup = {
+ id: preExecuteGroup.group.id,
+ level: preExecuteGroup.group.level,
+ parentId: preExecuteGroup.group.id,
+ type: "line",
+ };
}
- flatEntries.splice(insertAt, 0, { element:
renderTIContextPreamble(tiContext, "jsx", "Task Identity") });
+ flatEntries.splice(insertAt, 0, {
+ element: renderTIContextPreamble(tiContext, "jsx", "Task Identity"),
+ group: insertGroup,
+ });
}
return {