diff --git a/airflow-core/src/airflow/dag_processing/manager.py b/airflow-core/src/airflow/dag_processing/manager.py index df0f8f8748135..fa13c3c39cc28 100644 --- a/airflow-core/src/airflow/dag_processing/manager.py +++ b/airflow-core/src/airflow/dag_processing/manager.py @@ -156,7 +156,7 @@ def presence_key(self) -> tuple[str, Path]: @property def normalized_file_path_for_stats(self) -> str: """Return the relative file path normalized for use in stats tags.""" - return normalize_name_for_stats(str(self.rel_path)) + return normalize_name_for_stats(str(self.rel_path), log_warning=False) def _config_int_factory(section: str, key: str): diff --git a/airflow-core/tests/unit/dag_processing/test_manager.py b/airflow-core/tests/unit/dag_processing/test_manager.py index f1fb4b66c81fd..7bda30659a00e 100644 --- a/airflow-core/tests/unit/dag_processing/test_manager.py +++ b/airflow-core/tests/unit/dag_processing/test_manager.py @@ -3620,3 +3620,20 @@ def test_get_team_names_batches_and_caches(self, mock_get_team_names): # Two bundles resolved in a single batched query; the repeat call is served from cache. mock_get_team_names.assert_called_once() assert manager._bundle_name_to_team_name == {"bundle_a": "team_alpha", "bundle_b": "team_alpha"} + + +def test_normalized_file_path_for_stats_does_not_warn(caplog): + """ + rel_path always contains "/" for any nested DAG file, so normalizing it for stats + always requires substitution -- this must not log a warning on every DAG file, every + processing cycle. + """ + dag_file_info = DagFileInfo( + bundle_name="testing", bundle_path=TEST_DAGS_FOLDER, rel_path=Path("dags/test/test_dag.py") + ) + + with caplog.at_level(logging.WARNING, logger="airflow._shared.observability.metrics.stats"): + result = dag_file_info.normalized_file_path_for_stats + + assert result == "dags_test_test_dag.py" + assert caplog.entries == []