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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"user": "User",
"when": "When"
},
"filters": {
"eventType": "Event Type"
},
"title": "Audit Log"
},
"xcom": {
Expand Down
1 change: 1 addition & 0 deletions airflow-core/src/airflow/ui/src/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ export * from "./Breadcrumb";
export * from "./Clipboard";
export * from "./Popover";
export * from "./Checkbox";
export * from "./ResetButton";
9 changes: 9 additions & 0 deletions airflow-core/src/airflow/ui/src/constants/searchParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@
* under the License.
*/
export enum SearchParamsKeys {
AFTER = "after",
BEFORE = "before",
DAG_DISPLAY_NAME_PATTERN = "dag_display_name_pattern",
DAG_ID = "dag_id",
DAG_ID_PATTERN = "dag_id_pattern",
DEPENDENCIES = "dependencies",
END_DATE = "end_date",
EVENT_TYPE = "event_type",
EXCLUDED_EVENTS = "excluded_events",
FAVORITE = "favorite",
INCLUDED_EVENTS = "included_events",
KEY_PATTERN = "key_pattern",
LAST_DAG_RUN_STATE = "last_dag_run_state",
LIMIT = "limit",
Expand All @@ -37,6 +43,7 @@ export enum SearchParamsKeys {
RESPONSE_RECEIVED = "response_received",
RUN_AFTER_GTE = "run_after_gte",
RUN_AFTER_LTE = "run_after_lte",
RUN_ID = "run_id",
RUN_ID_PATTERN = "run_id_pattern",
RUN_TYPE = "run_type",
SORT = "sort",
Expand All @@ -45,9 +52,11 @@ export enum SearchParamsKeys {
STATE = "state",
TAGS = "tags",
TAGS_MATCH_MODE = "tags_match_mode",
TASK_ID = "task_id",
TASK_ID_PATTERN = "task_id_pattern",
TRIGGERING_USER_NAME_PATTERN = "triggering_user_name_pattern",
TRY_NUMBER = "try_number",
USER = "user",
VERSION_NUMBER = "version_number",
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import { useCallback, useState } from "react";
import { useSearchParams } from "react-router-dom";

import { useTableURLState } from "src/components/DataTable/useTableUrlState";
import { ResetButton } from "src/components/ui";
import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams";
import { useConfig } from "src/queries/useConfig";
import { useDagTagsInfinite } from "src/queries/useDagTagsInfinite";

import { FavoriteFilter } from "./FavoriteFilter";
import { PausedFilter } from "./PausedFilter";
import { ResetButton } from "./ResetButton";
import { StateFilters } from "./StateFilters";
import { TagFilter } from "./TagFilter";

Expand Down
60 changes: 51 additions & 9 deletions airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Box, ButtonGroup, Code, Flex, Heading, IconButton, useDisclosure } from "@chakra-ui/react";
import { ButtonGroup, Code, Flex, Heading, IconButton, useDisclosure, VStack } from "@chakra-ui/react";
import type { ColumnDef } from "@tanstack/react-table";
import dayjs from "dayjs";
import { useTranslation } from "react-i18next";
import { MdCompress, MdExpand } from "react-icons/md";
import { useParams } from "react-router-dom";
import { useParams, useSearchParams } from "react-router-dom";

import { useEventLogServiceGetEventLogs } from "openapi/queries";
import type { EventLogResponse } from "openapi/requests/types.gen";
Expand All @@ -29,6 +30,9 @@ import { useTableURLState } from "src/components/DataTable/useTableUrlState";
import { ErrorAlert } from "src/components/ErrorAlert";
import RenderedJsonField from "src/components/RenderedJsonField";
import Time from "src/components/Time";
import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams";

import { EventsFilters } from "./EventsFilters";

type EventsColumn = {
dagId?: string;
Expand Down Expand Up @@ -141,31 +145,66 @@ const eventsColumn = (
},
];

const {
AFTER: AFTER_PARAM,
BEFORE: BEFORE_PARAM,
DAG_ID: DAG_ID_PARAM,
EVENT_TYPE: EVENT_TYPE_PARAM,
MAP_INDEX: MAP_INDEX_PARAM,
RUN_ID: RUN_ID_PARAM,
TASK_ID: TASK_ID_PARAM,
TRY_NUMBER: TRY_NUMBER_PARAM,
USER: USER_PARAM,
}: SearchParamsKeysType = SearchParamsKeys;

export const Events = () => {
const { t: translate } = useTranslation("browse");
const { dagId, runId, taskId } = useParams();
const [searchParams] = useSearchParams();
const { setTableURLState, tableURLState } = useTableURLState();
const { pagination, sorting } = tableURLState;
const [sort] = sorting;
const { onClose, onOpen, open } = useDisclosure();

const afterFilter = searchParams.get(AFTER_PARAM);
const beforeFilter = searchParams.get(BEFORE_PARAM);
const dagIdFilter = searchParams.get(DAG_ID_PARAM);
const eventTypeFilter = searchParams.get(EVENT_TYPE_PARAM);
const mapIndexFilter = searchParams.get(MAP_INDEX_PARAM);
const runIdFilter = searchParams.get(RUN_ID_PARAM);
const taskIdFilter = searchParams.get(TASK_ID_PARAM);
const tryNumberFilter = searchParams.get(TRY_NUMBER_PARAM);
const userFilter = searchParams.get(USER_PARAM);

const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-when"];
// Convert string filters to appropriate types for API
const mapIndexNumber = mapIndexFilter === null ? undefined : parseInt(mapIndexFilter, 10);
const tryNumberNumber = tryNumberFilter === null ? undefined : parseInt(tryNumberFilter, 10);
// Handle date conversion - ensure valid ISO strings
const afterDate = afterFilter !== null && dayjs(afterFilter).isValid() ? afterFilter : undefined;
const beforeDate = beforeFilter !== null && dayjs(beforeFilter).isValid() ? beforeFilter : undefined;

const { data, error, isFetching, isLoading } = useEventLogServiceGetEventLogs(
{
dagId,
after: afterDate,
before: beforeDate,
dagId: dagId ?? dagIdFilter ?? undefined,
event: eventTypeFilter ?? undefined,
limit: pagination.pageSize,
mapIndex: mapIndexNumber,
offset: pagination.pageIndex * pagination.pageSize,
orderBy,
runId,
taskId,
owner: userFilter ?? undefined,
runId: runId ?? runIdFilter ?? undefined,
taskId: taskId ?? taskIdFilter ?? undefined,
tryNumber: tryNumberNumber,
},
undefined,
{ enabled: !isNaN(pagination.pageSize) },
);

return (
<Box>
<VStack alignItems="stretch" gap={4}>
<Flex alignItems="center" justifyContent="space-between">
{dagId === undefined && runId === undefined && taskId === undefined ? (
<Heading size="md">{translate("auditLog.title")}</Heading>
Expand All @@ -191,19 +230,22 @@ export const Events = () => {
</IconButton>
</ButtonGroup>
</Flex>

<EventsFilters urlDagId={dagId} urlRunId={runId} urlTaskId={taskId} />

<ErrorAlert error={error} />
<DataTable
columns={eventsColumn({ dagId, open, runId, taskId }, translate)}
data={data ? data.event_logs : []}
data={data?.event_logs ?? []}
displayMode="table"
initialState={tableURLState}
isFetching={isFetching}
isLoading={isLoading}
modelName={translate("auditLog.columns.event")}
onStateChange={setTableURLState}
skeletonCount={undefined}
total={data ? data.total_entries : 0}
total={data?.total_entries ?? 0}
/>
</Box>
</VStack>
);
};
Loading
Loading