Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion airflow-core/src/airflow/ui/src/mocks/handlers/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,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"]} />,
);
Expand All @@ -166,21 +166,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");

expect(preamble).toBeInTheDocument();
expect(sourceGroup).toBeInTheDocument();

// DOCUMENT_POSITION_FOLLOWING (4) is set when preamble comes after the source group summary
// eslint-disable-next-line no-bitwise
expect(sourceGroup.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 () => {
Expand Down
18 changes: 4 additions & 14 deletions airflow-core/src/airflow/ui/src/queries/useLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,14 @@ 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);

parsedLines = (() => {
type Group = { level: number; lines: Array<JSX.Element | "">; name: string };
const groupStack: Array<Group> = [];
const result: Array<JSX.Element | ""> = [];
let tiInsertAt: number | undefined;

parsedLines.forEach((line) => {
const text = innerText(line);
Expand All @@ -160,6 +159,9 @@ const parseLogs = ({
{finishedGroup.name}
</chakra.span>
</chakra.summary>
{finishedGroup.name === "Pre Execute" && tiContext !== undefined
? renderTIContextPreamble(tiContext, "jsx", "Task Identity")
: null}
{finishedGroup.lines}
</chakra.details>
</Box>
Expand All @@ -172,10 +174,6 @@ const parseLogs = ({
} else {
result.push(groupElement);
}

if (groupStack.length === 0 && finishedGroup.name.startsWith("Log message source details")) {
tiInsertAt = result.length;
}
}

return;
Expand All @@ -200,14 +198,6 @@ const parseLogs = ({
}
}

if (tiContext !== undefined) {
result.splice(
tiInsertAt ?? 0,
0,
renderTIContextPreamble(tiContext, "jsx", "Task Identity") as JSX.Element,
);
}

return result;
})();

Expand Down
Loading