Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link state icons in dashboard to list page with instances filtered by the state for the given duration. #46968

Merged
merged 5 commits into from
Feb 28, 2025
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
6 changes: 4 additions & 2 deletions airflow/ui/src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Props = {
readonly defaultValue: string;
readonly groupProps?: InputGroupProps;
readonly hideAdvanced?: boolean;
readonly hotkeyDisabled?: boolean;
readonly onChange: (value: string) => void;
readonly placeHolder: string;
};
Expand All @@ -42,6 +43,7 @@ export const SearchBar = ({
defaultValue,
groupProps,
hideAdvanced = false,
hotkeyDisabled = false,
onChange,
placeHolder,
}: Props) => {
Expand All @@ -60,7 +62,7 @@ export const SearchBar = ({
() => {
searchRef.current?.focus();
},
{ preventDefault: true },
{ enabled: !hotkeyDisabled, preventDefault: true },
);

return (
Expand All @@ -86,7 +88,7 @@ export const SearchBar = ({
Advanced Search
</Button>
)}
<Kbd size="sm">{metaKey}+K</Kbd>
{!hotkeyDisabled && <Kbd size="sm">{metaKey}+K</Kbd>}
</>
}
startElement={<FiSearch />}
Expand Down
3 changes: 3 additions & 0 deletions airflow/ui/src/constants/searchParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
* under the License.
*/
export enum SearchParamsKeys {
END_DATE = "end_date",
LAST_DAG_RUN_STATE = "last_dag_run_state",
LIMIT = "limit",
NAME_PATTERN = "name_pattern",
OFFSET = "offset",
PAUSED = "paused",
SORT = "sort",
START_DATE = "start_date",
STATE = "state",
TAGS = "tags",
VERSION_NUMBER = "version_number",
}
Expand Down
12 changes: 10 additions & 2 deletions airflow/ui/src/pages/DagRuns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ import { RunTypeIcon } from "src/components/RunTypeIcon";
import { StateBadge } from "src/components/StateBadge";
import Time from "src/components/Time";
import { Select } from "src/components/ui";
import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searchParams";
import { dagRunStateOptions as stateOptions } from "src/constants/stateOptions";
import { capitalize, getDuration, useAutoRefresh, isStatePending } from "src/utils";

type DagRunRow = { row: { original: DAGRunResponse } };
const {
END_DATE: END_DATE_PARAM,
START_DATE: START_DATE_PARAM,
STATE: STATE_PARAM,
}: SearchParamsKeysType = SearchParamsKeys;

const runColumns = (dagId?: string): Array<ColumnDef<DAGRunResponse>> => [
...(Boolean(dagId)
Expand Down Expand Up @@ -108,8 +114,6 @@ const runColumns = (dagId?: string): Array<ColumnDef<DAGRunResponse>> => [
},
];

const STATE_PARAM = "state";

export const DagRuns = () => {
const { dagId } = useParams();
const [searchParams, setSearchParams] = useSearchParams();
Expand All @@ -120,15 +124,19 @@ export const DagRuns = () => {
const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "-run_after";

const filteredState = searchParams.get(STATE_PARAM);
const startDate = searchParams.get(START_DATE_PARAM);
const endDate = searchParams.get(END_DATE_PARAM);

const refetchInterval = useAutoRefresh({});

const { data, error, isLoading } = useDagRunServiceGetDagRuns(
{
dagId: dagId ?? "~",
endDateLte: endDate ?? undefined,
limit: pagination.pageSize,
offset: pagination.pageIndex * pagination.pageSize,
orderBy,
startDateGte: startDate ?? undefined,
state: filteredState === null ? undefined : [filteredState],
},
undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ import { MetricSection } from "./MetricSection";

type DagRunMetricsProps = {
readonly dagRunStates: DAGRunStates;
readonly endDate: string;
readonly startDate: string;
readonly total: number;
};

const DAGRUN_STATES: Array<keyof DAGRunStates> = ["queued", "running", "success", "failed"];

export const DagRunMetrics = ({ dagRunStates, total }: DagRunMetricsProps) => (
export const DagRunMetrics = ({ dagRunStates, endDate, startDate, total }: DagRunMetricsProps) => (
<Box borderRadius={5} borderWidth={1} p={2}>
<HStack mb={4}>
<StateBadge colorPalette="blue" fontSize="md" variant="solid">
Expand All @@ -41,7 +43,15 @@ export const DagRunMetrics = ({ dagRunStates, total }: DagRunMetricsProps) => (
<Heading size="md">Dag Runs</Heading>
</HStack>
{DAGRUN_STATES.map((state) => (
<MetricSection key={state} runs={dagRunStates[state]} state={state} total={total} />
<MetricSection
endDate={endDate}
key={state}
kind="dag_runs"
runs={dagRunStates[state]}
startDate={startDate}
state={state}
total={total}
/>
))}
</Box>
);
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,18 @@ export const HistoricalMetrics = () => {
{isLoading ? <MetricSectionSkeleton /> : undefined}
{!isLoading && data !== undefined && (
<Box>
<DagRunMetrics dagRunStates={data.dag_run_states} total={dagRunTotal} />
<TaskInstanceMetrics taskInstanceStates={data.task_instance_states} total={taskRunTotal} />
<DagRunMetrics
dagRunStates={data.dag_run_states}
endDate={endDate}
startDate={startDate}
total={dagRunTotal}
/>
<TaskInstanceMetrics
endDate={endDate}
startDate={startDate}
taskInstanceStates={data.task_instance_states}
total={taskRunTotal}
/>
</Box>
)}
</GridItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/
import { Box, Flex, HStack, VStack, Text } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";

import type { TaskInstanceState } from "openapi/requests/types.gen";
import { StateBadge } from "src/components/StateBadge";
Expand All @@ -26,12 +27,15 @@ const BAR_WIDTH = 100;
const BAR_HEIGHT = 5;

type MetricSectionProps = {
readonly endDate: string;
readonly kind: string;
readonly runs: number;
readonly startDate: string;
readonly state: TaskInstanceState;
readonly total: number;
};

export const MetricSection = ({ runs, state, total }: MetricSectionProps) => {
export const MetricSection = ({ endDate, kind, runs, startDate, state, total }: MetricSectionProps) => {
// Calculate the given state as a percentage of total and draw a bar
// in state's color with width as state's percentage and remaining width filed as gray
const statePercent = total === 0 ? 0 : ((runs / total) * 100).toFixed(2);
Expand All @@ -42,9 +46,11 @@ export const MetricSection = ({ runs, state, total }: MetricSectionProps) => {
<VStack align="left" gap={1} mb={4} ml={0} pl={0}>
<Flex justify="space-between">
<HStack>
<StateBadge fontSize="md" state={state}>
{runs}
</StateBadge>
<RouterLink to={`/${kind}?state=${state}&start_date=${startDate}&end_date=${endDate}`}>
<StateBadge fontSize="md" state={state}>
{runs}
</StateBadge>
</RouterLink>
<Text>
{state
.split("_")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { StateBadge } from "src/components/StateBadge";
import { MetricSection } from "./MetricSection";

type TaskInstanceMetricsProps = {
readonly endDate: string;
readonly startDate: string;
readonly taskInstanceStates: TaskInstanceStateCount;
readonly total: number;
};
Expand All @@ -44,7 +46,12 @@ const TASK_STATES: Array<keyof TaskInstanceStateCount> = [
"deferred",
];

export const TaskInstanceMetrics = ({ taskInstanceStates, total }: TaskInstanceMetricsProps) => (
export const TaskInstanceMetrics = ({
endDate,
startDate,
taskInstanceStates,
total,
}: TaskInstanceMetricsProps) => (
<Box borderRadius={5} borderWidth={1} mt={2} p={2}>
<HStack mb={4}>
<StateBadge colorPalette="blue" fontSize="md" variant="solid">
Expand All @@ -58,8 +65,11 @@ export const TaskInstanceMetrics = ({ taskInstanceStates, total }: TaskInstanceM
).map((state) =>
taskInstanceStates[state] > 0 ? (
<MetricSection
endDate={endDate}
key={state}
kind="task_instances"
runs={taskInstanceStates[state]}
startDate={startDate}
state={state as TaskInstanceState}
total={total}
/>
Expand Down
Loading