diff --git a/shared/logging/src/airflow_shared/logging/percent_formatter.py b/shared/logging/src/airflow_shared/logging/percent_formatter.py index b08024621e69d..78e4b82a81034 100644 --- a/shared/logging/src/airflow_shared/logging/percent_formatter.py +++ b/shared/logging/src/airflow_shared/logging/percent_formatter.py @@ -50,6 +50,16 @@ def __getitem__(self, key): # Roughly compatible with names from https://github.com/python/cpython/blob/v3.13.7/Lib/logging/__init__.py#L571 # Plus with ColoredLog added in + # If there is no callsite info (often for stdout/stderr), show the same sort of thing that stdlib + # logging would + # https://github.com/python/cpython/blob/d3c888b4ec15dbd7d6b6ef4f15b558af77c228af/Lib/logging/__init__.py#L1652C34-L1652C48 + if key == "lineno": + return self.event.get("lineno", 0) + if key == "filename": + return self.event.get("filename", "(unknown file)") + if key == "funcName": + return self.event.get("funcName", "(unknown function)") + if key in PercentFormatRender.callsite_parameters: return self.event.get(PercentFormatRender.callsite_parameters[key].value) if key == "name": diff --git a/shared/logging/tests/logging/test_percent_formatter.py b/shared/logging/tests/logging/test_percent_formatter.py new file mode 100644 index 0000000000000..efcafd1353a17 --- /dev/null +++ b/shared/logging/tests/logging/test_percent_formatter.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from unittest import mock + +from airflow_shared.logging.percent_formatter import PercentFormatRender + + +class TestPercentFormatRender: + def test_no_callsite(self): + fmter = PercentFormatRender("%(filename)s:%(lineno)d %(message)s") + + formatted = fmter(mock.Mock(name="Logger"), "info", {"event": "our msg"}) + + assert formatted == "(unknown file):0 our msg"