This is an automated email from the ASF dual-hosted git repository.
shahar1 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 f04f123b2cc Prevent Dag processor crashes with AWS CloudWatch when its
log directory is outside `base_log_folder` (#74929)
f04f123b2cc is described below
commit f04f123b2cc2f47fe1bcca87f85105dd6c48ea2d
Author: Shahar Epstein <[email protected]>
AuthorDate: Mon Oct 19 22:17:42 2026 +0300
Prevent Dag processor crashes with AWS CloudWatch when its log directory is
outside `base_log_folder` (#74929)
The CloudWatch log processor resolved every log file's path relative to
base_log_folder without handling files that live elsewhere. With
dag_processor_child_process_log_directory set outside base_log_folder,
the first log line from a Dag file processor raised ValueError and took
down the whole Dag processor, so no Dag was parsed. Remote log upload
already skips such files.
---
.../providers/amazon/aws/log/cloudwatch_task_handler.py | 10 +++++++++-
.../unit/amazon/aws/log/test_cloudwatch_task_handler.py | 15 +++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git
a/providers/amazon/src/airflow/providers/amazon/aws/log/cloudwatch_task_handler.py
b/providers/amazon/src/airflow/providers/amazon/aws/log/cloudwatch_task_handler.py
index 192d8d10566..5a71dc4ab70 100644
---
a/providers/amazon/src/airflow/providers/amazon/aws/log/cloudwatch_task_handler.py
+++
b/providers/amazon/src/airflow/providers/amazon/aws/log/cloudwatch_task_handler.py
@@ -182,7 +182,15 @@ class CloudWatchRemoteLogIO(LoggingMixin): # noqa: D101
# The handler MUST be initted here, before the processor is actually
used to log anything.
# Otherwise, logging that occurs during the creation of the handler
can create infinite loops.
_ = self.handler
- from airflow.sdk.log import relative_path_from_logger
+ from airflow.sdk.log import relative_path_from_logger as
_relative_path_from_logger
+
+ def relative_path_from_logger(logger) -> Path | None:
+ try:
+ return _relative_path_from_logger(logger)
+ except ValueError:
+ # Skip log files outside ``base_log_folder``, such as a Dag
processor log directory
+ # configured elsewhere, as ``upload_to_remote`` does.
+ return None
def proc(logger: structlog.typing.WrappedLogger, method_name: str,
event: structlog.typing.EventDict):
if not logger or not (stream_name :=
relative_path_from_logger(logger)):
diff --git
a/providers/amazon/tests/unit/amazon/aws/log/test_cloudwatch_task_handler.py
b/providers/amazon/tests/unit/amazon/aws/log/test_cloudwatch_task_handler.py
index c924658ea2e..3775e9dd208 100644
--- a/providers/amazon/tests/unit/amazon/aws/log/test_cloudwatch_task_handler.py
+++ b/providers/amazon/tests/unit/amazon/aws/log/test_cloudwatch_task_handler.py
@@ -316,6 +316,21 @@ class TestCloudRemoteLogIO:
dag_dir = self.local_log_location / "dag_id=a"
assert dag_dir.exists()
+ @mock.patch("airflow.sdk.log.relative_path_from_logger")
+ @mock.patch.object(CloudWatchRemoteLogIO, "handler",
new_callable=mock.PropertyMock)
+ def test_processors_skip_log_file_outside_base_log_folder(self,
mock_handler, mock_relative_path):
+ mock_relative_path.side_effect = ValueError("'/elsewhere/x.log' is not
in the subpath of '/logs'")
+ subject = CloudWatchRemoteLogIO(
+ base_log_folder=self.local_log_location,
+
log_group_arn=f"arn:aws:logs:{self.region_name}:11111111:log-group:{self.remote_log_group}",
+ )
+ event = {"event": "Hi"}
+
+ result = subject.processors[0](mock.MagicMock(), "info", event)
+
+ assert result is event
+ mock_handler.return_value.handle.assert_not_called()
+
@time_machine.travel(timezone.datetime(2025, 3, 27, 21, 58, 1, 2345),
tick=False)
def test_log_message(self):
# Use a context instead of a decorator on the test method because we
need access to self to