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 1bb880df42f Add team_name tags to Amazon executor metrics (#69072)
1bb880df42f is described below

commit 1bb880df42f8c185a27eca1e3d4ee7fee9c8d225
Author: Justin Pakzad <[email protected]>
AuthorDate: Mon Jun 29 18:37:19 2026 -0400

    Add team_name tags to Amazon executor metrics (#69072)
---
 .../aws/executors/aws_lambda/lambda_executor.py    | 10 ++++++--
 .../amazon/aws/executors/batch/batch_executor.py   | 11 ++++++---
 .../amazon/aws/executors/ecs/ecs_executor.py       | 10 ++++++--
 .../executors/aws_lambda/test_lambda_executor.py   | 27 ++++++++++++++++++++++
 .../aws/executors/batch/test_batch_executor.py     | 25 ++++++++++++++++++++
 .../amazon/aws/executors/ecs/test_ecs_executor.py  | 27 +++++++++++++++++++++-
 6 files changed, 102 insertions(+), 8 deletions(-)

diff --git 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/aws_lambda/lambda_executor.py
 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/aws_lambda/lambda_executor.py
index 72455165e83..5d30d5c84a2 100644
--- 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/aws_lambda/lambda_executor.py
+++ 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/aws_lambda/lambda_executor.py
@@ -44,6 +44,7 @@ from airflow.providers.amazon.aws.hooks.lambda_function 
import LambdaHook
 from airflow.providers.amazon.aws.hooks.sqs import SqsHook
 from airflow.providers.amazon.version_compat import AIRFLOW_V_3_0_PLUS, 
AIRFLOW_V_3_3_PLUS
 from airflow.providers.common.compat.sdk import AirflowException, Stats, 
timezone
+from airflow.utils.helpers import prune_dict
 
 if TYPE_CHECKING:
     from sqlalchemy.orm import Session
@@ -94,7 +95,10 @@ class AwsLambdaExecutor(BaseExecutor):
             from airflow.providers.common.compat.sdk import conf
 
             self.conf = conf
-
+        # TODO: Remove this fallback once the min Airflow version for 
providers is >= 3.1
+        # (BaseExecutor.team_name is always defined from Airflow 3.1 onward).
+        if not hasattr(self, "team_name"):
+            self.team_name = None
         self.lambda_function_name = self.conf.get(CONFIG_GROUP_NAME, 
AllLambdaConfigKeys.FUNCTION_NAME)
         self.sqs_queue_url = self.conf.get(CONFIG_GROUP_NAME, 
AllLambdaConfigKeys.QUEUE_URL)
         self.dlq_url = self.conf.get(CONFIG_GROUP_NAME, 
AllLambdaConfigKeys.DLQ_URL)
@@ -558,7 +562,9 @@ class AwsLambdaExecutor(BaseExecutor):
 
         :param tis: The task instances to adopt.
         """
-        with Stats.timer("lambda_executor.adopt_task_instances.duration"):
+        with Stats.timer(
+            "lambda_executor.adopt_task_instances.duration", 
tags=prune_dict({"team_name": self.team_name})
+        ):
             adopted_tis: list[TaskInstance] = []
 
             if serialized_workload_keys := [
diff --git 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/batch/batch_executor.py
 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/batch/batch_executor.py
index 74614961f89..00c7dcb7881 100644
--- 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/batch/batch_executor.py
+++ 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/batch/batch_executor.py
@@ -35,7 +35,7 @@ from 
airflow.providers.amazon.aws.executors.utils.exponential_backoff_retry impo
 from airflow.providers.amazon.aws.hooks.batch_client import BatchClientHook
 from airflow.providers.amazon.version_compat import AIRFLOW_V_3_0_PLUS, 
AIRFLOW_V_3_3_PLUS
 from airflow.providers.common.compat.sdk import AirflowException, Stats, 
timezone
-from airflow.utils.helpers import merge_dicts
+from airflow.utils.helpers import merge_dicts, prune_dict
 
 if TYPE_CHECKING:
     from sqlalchemy.orm import Session
@@ -116,7 +116,10 @@ class AwsBatchExecutor(BaseExecutor):
             from airflow.providers.common.compat.sdk import conf
 
             self.conf = conf
-
+        # TODO: Remove this fallback once the min Airflow version for 
providers is >= 3.1
+        # (BaseExecutor.team_name is always defined from Airflow 3.1 onward).
+        if not hasattr(self, "team_name"):
+            self.team_name = None
         self.attempts_since_last_successful_connection = 0
         self.load_batch_connection(check_connection=False)
         self.IS_BOTO_CONNECTION_HEALTHY = False
@@ -540,7 +543,9 @@ class AwsBatchExecutor(BaseExecutor):
 
         Anything that is not adopted will be cleared by the scheduler and 
becomes eligible for re-scheduling.
         """
-        with Stats.timer("batch_executor.adopt_task_instances.duration"):
+        with Stats.timer(
+            "batch_executor.adopt_task_instances.duration", 
tags=prune_dict({"team_name": self.team_name})
+        ):
             adopted_tis: list[TaskInstance] = []
 
             if job_ids := [ti.external_executor_id for ti in tis if 
ti.external_executor_id]:
diff --git 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/ecs/ecs_executor.py
 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/ecs/ecs_executor.py
index 644fbb29ed6..cba439ddc62 100644
--- 
a/providers/amazon/src/airflow/providers/amazon/aws/executors/ecs/ecs_executor.py
+++ 
b/providers/amazon/src/airflow/providers/amazon/aws/executors/ecs/ecs_executor.py
@@ -50,7 +50,7 @@ from 
airflow.providers.amazon.aws.executors.utils.exponential_backoff_retry impo
 from airflow.providers.amazon.aws.hooks.ecs import EcsHook
 from airflow.providers.amazon.version_compat import AIRFLOW_V_3_0_PLUS, 
AIRFLOW_V_3_3_PLUS
 from airflow.providers.common.compat.sdk import AirflowException, Stats, 
timezone
-from airflow.utils.helpers import merge_dicts
+from airflow.utils.helpers import merge_dicts, prune_dict
 from airflow.utils.state import State
 
 if TYPE_CHECKING:
@@ -126,6 +126,10 @@ class AwsEcsExecutor(BaseExecutor):
             from airflow.providers.common.compat.sdk import conf
 
             self.conf = conf
+        # TODO: Remove this fallback once the min Airflow version for 
providers is >= 3.1
+        # (BaseExecutor.team_name is always defined from Airflow 3.1 onward).
+        if not hasattr(self, "team_name"):
+            self.team_name = None
 
         self.cluster = self.conf.get(CONFIG_GROUP_NAME, 
AllEcsConfigKeys.CLUSTER)
         self.container_name = self.conf.get(CONFIG_GROUP_NAME, 
AllEcsConfigKeys.CONTAINER_NAME)
@@ -641,7 +645,9 @@ class AwsEcsExecutor(BaseExecutor):
 
         Anything that is not adopted will be cleared by the scheduler and 
becomes eligible for re-scheduling.
         """
-        with Stats.timer("ecs_executor.adopt_task_instances.duration"):
+        with Stats.timer(
+            "ecs_executor.adopt_task_instances.duration", 
tags=prune_dict({"team_name": self.team_name})
+        ):
             adopted_tis: list[TaskInstance] = []
 
             if task_arns := [ti.external_executor_id for ti in tis if 
ti.external_executor_id]:
diff --git 
a/providers/amazon/tests/unit/amazon/aws/executors/aws_lambda/test_lambda_executor.py
 
b/providers/amazon/tests/unit/amazon/aws/executors/aws_lambda/test_lambda_executor.py
index 284865285f1..6613b8e39d7 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/executors/aws_lambda/test_lambda_executor.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/executors/aws_lambda/test_lambda_executor.py
@@ -1082,6 +1082,33 @@ class TestAwsLambdaExecutor:
 
         assert len(not_adopted) == 0
 
+    @pytest.mark.parametrize(
+        ("team_name", "expected_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="Multi-team support 
requires Airflow 3.1+"
+                ),
+            ),
+        ],
+    )
+    @mock.patch.object(lambda_executor.Stats, "timer")
+    def test_try_adopt_task_instances_emits_team_name_tag(
+        self, mock_timer, mock_executor, team_name, expected_tags
+    ):
+        """Test that the adopt task instances duration metric is tagged with 
the team name."""
+        mock_executor.team_name = team_name
+
+        mock_executor.try_adopt_task_instances([])
+
+        mock_timer.assert_called_once_with(
+            "lambda_executor.adopt_task_instances.duration", tags=expected_tags
+        )
+
     
@mock.patch("airflow.providers.amazon.aws.executors.aws_lambda.lambda_executor.timezone")
     def test_end_timeout(self, mock_timezone, mock_executor, mock_airflow_key):
         """Test that executor can end successfully; waiting for all workloads 
to naturally exit."""
diff --git 
a/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py 
b/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
index 211ed64acf6..f5800232610 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
@@ -931,6 +931,31 @@ class TestAwsBatchExecutor:
             assert submit_kwargs["jobDefinition"] == "some-job-def"
             assert submit_kwargs["jobName"] == "some-job-name"
 
+    @pytest.mark.parametrize(
+        ("team_name", "expected_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="Multi-team support 
requires Airflow 3.1+"
+                ),
+            ),
+        ],
+    )
+    @mock.patch.object(batch_executor.Stats, "timer")
+    def test_try_adopt_task_instances_emits_team_name_tag(
+        self, mock_timer, mock_executor, team_name, expected_tags
+    ):
+        """Test that the adopt task instances duration metric is tagged with 
the team name."""
+        mock_executor.team_name = team_name
+
+        mock_executor.try_adopt_task_instances([])
+
+        
mock_timer.assert_called_once_with("batch_executor.adopt_task_instances.duration",
 tags=expected_tags)
+
 
 class TestBatchExecutorConfig:
     @staticmethod
diff --git 
a/providers/amazon/tests/unit/amazon/aws/executors/ecs/test_ecs_executor.py 
b/providers/amazon/tests/unit/amazon/aws/executors/ecs/test_ecs_executor.py
index de5a17acf96..b7c25d51277 100644
--- a/providers/amazon/tests/unit/amazon/aws/executors/ecs/test_ecs_executor.py
+++ b/providers/amazon/tests/unit/amazon/aws/executors/ecs/test_ecs_executor.py
@@ -60,7 +60,7 @@ from airflow.version import version as airflow_version_str
 
 from tests_common import RUNNING_TESTS_AGAINST_AIRFLOW_PACKAGES
 from tests_common.test_utils.config import conf_vars
-from tests_common.test_utils.version_compat import AIRFLOW_V_3_0_PLUS, 
AIRFLOW_V_3_3_PLUS
+from tests_common.test_utils.version_compat import AIRFLOW_V_3_0_PLUS, 
AIRFLOW_V_3_1_PLUS, AIRFLOW_V_3_3_PLUS
 
 airflow_version = VersionInfo(*map(int, airflow_version_str.split(".")[:3]))
 
@@ -1334,6 +1334,31 @@ class TestAwsEcsExecutor:
         # The remaining one task is unable to be adopted.
         assert len(not_adopted_tasks) == 1
 
+    @pytest.mark.parametrize(
+        ("team_name", "expected_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="Multi-team support 
requires Airflow 3.1+"
+                ),
+            ),
+        ],
+    )
+    @mock.patch.object(ecs_executor.Stats, "timer")
+    def test_try_adopt_task_instances_emits_team_name_tag(
+        self, mock_timer, mock_executor, team_name, expected_tags
+    ):
+        """Test that the adopt task instances duration metric is tagged with 
the team name."""
+        mock_executor.team_name = team_name
+
+        mock_executor.try_adopt_task_instances([])
+
+        
mock_timer.assert_called_once_with("ecs_executor.adopt_task_instances.duration",
 tags=expected_tags)
+
 
 class TestEcsExecutorConfig:
     @pytest.fixture

Reply via email to