This is an automated email from the ASF dual-hosted git repository.
ferruzzi 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 dc5ddd26202 Add the team_name tag to the Celery executor
task_timeout_error (#69092)
dc5ddd26202 is described below
commit dc5ddd26202f972f634a6ee9ce25f04f17669ad7
Author: SameerMesiah97 <[email protected]>
AuthorDate: Wed Jul 8 00:50:13 2026 +0100
Add the team_name tag to the Celery executor task_timeout_error (#69092)
---
.../providers/celery/executors/celery_executor.py | 3 +-
.../unit/celery/executors/test_celery_executor.py | 60 +++++++++++++++++++++-
2 files changed, 61 insertions(+), 2 deletions(-)
diff --git
a/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
b/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
index 7fc388c9608..ba3af24415a 100644
--- a/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
+++ b/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
@@ -44,6 +44,7 @@ from airflow.providers.celery.executors import (
)
from airflow.providers.celery.version_compat import AIRFLOW_V_3_0_PLUS,
AIRFLOW_V_3_2_PLUS
from airflow.providers.common.compat.sdk import AirflowTaskTimeout, Stats
+from airflow.utils.helpers import prune_dict
from airflow.utils.state import TaskInstanceState
log = logging.getLogger(__name__)
@@ -210,7 +211,7 @@ class CeleryExecutor(BaseExecutor):
):
retries = self.workload_publish_retries[key]
if retries < self.workload_publish_max_retries:
- Stats.incr("celery.task_timeout_error")
+ Stats.incr("celery.task_timeout_error",
tags=prune_dict({"team_name": self.team_name}))
self.log.info(
"[Try %s of %s] Celery Task Timeout Error for
Workload: (%s).",
self.workload_publish_retries[key] + 1,
diff --git
a/providers/celery/tests/unit/celery/executors/test_celery_executor.py
b/providers/celery/tests/unit/celery/executors/test_celery_executor.py
index c349efa32cb..f66c8e81ab3 100644
--- a/providers/celery/tests/unit/celery/executors/test_celery_executor.py
+++ b/providers/celery/tests/unit/celery/executors/test_celery_executor.py
@@ -39,7 +39,7 @@ from airflow.models.dag import DAG
from airflow.models.taskinstance import TaskInstance, TaskInstanceKey
from airflow.providers.celery.executors import celery_executor,
celery_executor_utils, default_celery
from airflow.providers.celery.executors.celery_executor import CeleryExecutor
-from airflow.providers.common.compat.sdk import conf
+from airflow.providers.common.compat.sdk import AirflowTaskTimeout, conf
from airflow.utils.state import State
from tests_common.test_utils import db
@@ -216,6 +216,64 @@ class TestCeleryExecutor:
]
mock_stats_gauge.assert_has_calls(calls)
+ @pytest.mark.backend("mysql", "postgres")
+ @pytest.mark.parametrize(
+ ("team_name", "tags"),
+ [
+ pytest.param(
+ None,
+ {},
+ id="without_team",
+ ),
+ pytest.param(
+ "team_a",
+ {"team_name": "team_a"},
+ id="with_team",
+ marks=pytest.mark.skipif(
+ not AIRFLOW_V_3_1_PLUS,
+ reason="team_name metrics require Airflow 3.1+",
+ ),
+ ),
+ ],
+ )
+ @mock.patch("airflow.providers.celery.executors.celery_executor.Stats")
+ def test_send_workloads_emits_task_timeout_metric(
+ self,
+ mock_stats,
+ team_name,
+ tags,
+ ):
+ with _prepare_app():
+ executor = celery_executor.CeleryExecutor()
+ executor.team_name = team_name
+
+ key = TaskInstanceKey(
+ dag_id="dag",
+ task_id="task",
+ run_id="run",
+ try_number=1,
+ )
+ timeout = AirflowTaskTimeout()
+ exception = celery_executor_utils.ExceptionWithTraceback(timeout,
"traceback")
+
+ executor.workload_publish_max_retries = 3
+ executor.workload_publish_retries[key] = 0
+ executor.queued_tasks[key] = mock.Mock()
+
+ with mock.patch.object(
+ executor,
+ "_send_workloads_to_celery",
+ return_value=[(key, None, exception)],
+ ):
+ executor._send_workloads([mock.Mock()])
+
+ mock_stats.incr.assert_called_once_with(
+ "celery.task_timeout_error",
+ tags=tags,
+ )
+
+ assert executor.workload_publish_retries[key] == 1
+
@pytest.mark.skipif(AIRFLOW_V_3_0_PLUS, reason="Airflow 3 doesn't have
execute_command anymore")
@pytest.mark.parametrize(
("command", "raise_exception"),