Skip to content

Commit d43b468

Browse files
authored
Use Task Display Name in Grid if existing (apache#56393)
* Use Task Display Name in Grid if existing * Consider short task ID w/o prefix if no display name * Add some tests with labels on tasks * Apply ruff
1 parent e651ba9 commit d43b468

File tree

4 files changed

+21
-17
lines changed

4 files changed

+21
-17
lines changed

airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,18 +196,18 @@ def _collect_ids(nodes: list[dict[str, Any]]) -> set[str]:
196196
return ids
197197

198198
existing_ids = _collect_ids(merged_nodes)
199-
historical_task_ids = session.scalars(
200-
select(TaskInstance.task_id)
199+
historical_tasks = session.execute(
200+
select(TaskInstance.task_id, TaskInstance.task_display_name)
201201
.join(TaskInstance.dag_run)
202202
.where(TaskInstance.dag_id == dag_id, DagRun.id.in_(run_ids))
203203
.distinct()
204204
)
205-
for task_id in historical_task_ids:
205+
for task_id, task_display_name in historical_tasks:
206206
if task_id not in existing_ids:
207207
merged_nodes.append(
208208
{
209209
"id": task_id,
210-
"label": task_id,
210+
"label": task_display_name,
211211
"is_mapped": None,
212212
"children": None,
213213
}

airflow-core/src/airflow/api_fastapi/core_api/services/ui/task_group.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from airflow.configuration import conf
2727
from airflow.models.mappedoperator import MappedOperator, is_mapped
28+
from airflow.sdk import TaskGroup
2829
from airflow.serialization.serialized_objects import SerializedBaseOperator
2930

3031

@@ -90,15 +91,17 @@ def task_group_to_dict_grid(task_item_or_group, parent_group_is_mapped=False):
9091
setup_teardown_type = "setup"
9192
elif task.is_teardown is True:
9293
setup_teardown_type = "teardown"
94+
# we explicitly want the short task ID here, not the full doted notation if in a group
95+
task_display_name = task.task_display_name if task.task_display_name != task.task_id else task.label
9396
return {
9497
"id": task.task_id,
95-
"label": task.label,
98+
"label": task_display_name,
9699
"is_mapped": mapped,
97100
"children": None,
98101
"setup_teardown_type": setup_teardown_type,
99102
}
100103

101-
task_group = task_item_or_group
104+
task_group: TaskGroup = task_item_or_group
102105
task_group_sort = get_task_group_children_getter()
103106
mapped = is_mapped(task_group)
104107
children = [
@@ -108,7 +111,7 @@ def task_group_to_dict_grid(task_item_or_group, parent_group_is_mapped=False):
108111

109112
return {
110113
"id": task_group.group_id,
111-
"label": task_group.label,
114+
"label": task_group.group_display_name or task_group.label,
112115
"is_mapped": mapped or None,
113116
"children": children or None,
114117
}

airflow-core/src/airflow/ui/src/pages/TaskInstance/Header.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ export const Header = ({
125125
isRefreshing={isRefreshing}
126126
state={taskInstance.state}
127127
stats={stats}
128-
subTitle={<Time datetime={taskInstance.start_date} />}
129128
title={`${taskInstance.task_display_name}${taskInstance.map_index > -1 ? ` [${taskInstance.rendered_map_index ?? taskInstance.map_index}]` : ""}`}
130129
/>
131130
</Box>

airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_grid.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,19 @@
8484
"is_mapped": True,
8585
"label": "mapped_task_group",
8686
},
87-
{"id": "task", "label": "task"},
87+
{"id": "task", "label": "A Beautiful Task Name 🚀"},
8888
{
8989
"children": [
9090
{
9191
"children": [
9292
{
9393
"id": "task_group.inner_task_group.inner_task_group_sub_task",
9494
"is_mapped": True,
95-
"label": "inner_task_group_sub_task",
95+
"label": "Inner Task Group Sub Task Label",
9696
}
9797
],
9898
"id": "task_group.inner_task_group",
99-
"label": "inner_task_group",
99+
"label": "My Inner Task Group",
100100
},
101101
{"id": "task_group.mapped_task", "is_mapped": True, "label": "mapped_task"},
102102
],
@@ -121,7 +121,7 @@ def setup(dag_maker, session=None):
121121

122122
# DAG 1
123123
with dag_maker(dag_id=DAG_ID, serialized=True, session=session) as dag:
124-
task = EmptyOperator(task_id=TASK_ID)
124+
task = EmptyOperator(task_id=TASK_ID, task_display_name="A Beautiful Task Name 🚀")
125125

126126
@task_group
127127
def mapped_task_group(arg1):
@@ -131,8 +131,10 @@ def mapped_task_group(arg1):
131131

132132
with TaskGroup(group_id=TASK_GROUP_ID):
133133
MockOperator.partial(task_id=MAPPED_TASK_ID).expand(arg1=["a", "b", "c", "d"])
134-
with TaskGroup(group_id=INNER_TASK_GROUP):
135-
MockOperator.partial(task_id=INNER_TASK_GROUP_SUB_TASK).expand(arg1=["a", "b"])
134+
with TaskGroup(group_id=INNER_TASK_GROUP, group_display_name="My Inner Task Group"):
135+
MockOperator.partial(
136+
task_id=INNER_TASK_GROUP_SUB_TASK, task_display_name="Inner Task Group Sub Task Label"
137+
).expand(arg1=["a", "b"])
136138

137139
# Mapped but never expanded. API should not crash, but count this as one no-status ti.
138140
MockOperator.partial(task_id=MAPPED_TASK_ID_2).expand(arg1=task.output)
@@ -480,19 +482,19 @@ def test_get_dag_structure(self, session, test_client):
480482
"is_mapped": True,
481483
"label": "mapped_task_group",
482484
},
483-
{"id": "task", "label": "task"},
485+
{"id": "task", "label": "A Beautiful Task Name 🚀"},
484486
{
485487
"children": [
486488
{
487489
"children": [
488490
{
489491
"id": "task_group.inner_task_group.inner_task_group_sub_task",
490492
"is_mapped": True,
491-
"label": "inner_task_group_sub_task",
493+
"label": "Inner Task Group Sub Task Label",
492494
}
493495
],
494496
"id": "task_group.inner_task_group",
495-
"label": "inner_task_group",
497+
"label": "My Inner Task Group",
496498
},
497499
{"id": "task_group.mapped_task", "is_mapped": True, "label": "mapped_task"},
498500
],

0 commit comments

Comments
 (0)