Skip to content

Commit 10b841c

Browse files
committed
fix: split event sources for remote logging 3.2.2 test
1 parent bfb9d12 commit 10b841c

1 file changed

Lines changed: 43 additions & 7 deletions

File tree

tests/templates/kuttl/remote-logging/remote-logging-metrics.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,50 @@ def exception_handler(exception_type, exception, traceback):
1515
sys.excepthook = exception_handler
1616

1717

18-
def collect_all_sources(payload):
19-
# Return a flat list of every source string found in payload['content'].
18+
def at_least_3_2(airflow_version: str) -> bool:
19+
# The log API response shape changed in Airflow 3.2 (see collect_all_sources).
20+
try:
21+
major, minor = (int(p) for p in airflow_version.split(".")[:2])
22+
except (ValueError, IndexError):
23+
# Unknown/garbled version: assume the current (>= 3.2) format.
24+
return True
25+
return (major, minor) >= (3, 2)
26+
27+
28+
def collect_all_sources(payload, airflow_version):
29+
# Return a flat list of every log-source string found in payload['content'].
30+
#
31+
# Airflow >= 3.2 exposes the (remote) log location as `event` lines wrapped in a
32+
# "Log message source details" group, e.g.:
33+
# {'event': '::group::Log message source details'}
34+
# {'event': 's3://my-bucket/.../attempt=1.log'}
35+
# {'event': '::endgroup::'}
36+
# Older Airflow 3.x returned the locations in a `sources` list per entry instead.
37+
if at_least_3_2(airflow_version):
38+
sources = []
39+
in_source_group = False
40+
for entry in payload.get("content", []):
41+
if not isinstance(entry, dict):
42+
continue
43+
event = entry.get("event", "")
44+
if event == "::group::Log message source details":
45+
in_source_group = True
46+
elif event == "::endgroup::":
47+
in_source_group = False
48+
elif in_source_group:
49+
sources.append(event)
50+
return sources
51+
2052
sources = []
2153
for entry in payload.get("content", []):
2254
if isinstance(entry, dict) and isinstance(entry.get("sources"), list):
2355
sources.extend(entry["sources"])
2456
return sources
2557

2658

27-
def prefix_is_matched(tasks, dag_run_id_root_url, headers, required_prefix) -> bool:
59+
def prefix_is_matched(
60+
tasks, dag_run_id_root_url, headers, required_prefix, airflow_version
61+
) -> bool:
2862
for ti in tasks["task_instances"]:
2963
task_id = ti["task_id"]
3064
try_number = ti["try_number"]
@@ -34,7 +68,7 @@ def prefix_is_matched(tasks, dag_run_id_root_url, headers, required_prefix) -> b
3468
params={"full_content": "true"},
3569
).json()
3670
print(f"Logs/full-content: {logs}")
37-
all_sources = collect_all_sources(logs)
71+
all_sources = collect_all_sources(logs, airflow_version)
3872
if not all_sources:
3973
print("No 'sources' arrays were found yet in the payload...")
4074
else:
@@ -51,7 +85,7 @@ def prefix_is_matched(tasks, dag_run_id_root_url, headers, required_prefix) -> b
5185
return False
5286

5387

54-
def remote_logging() -> None:
88+
def remote_logging(airflow_version: str) -> None:
5589
now = datetime.now(timezone.utc)
5690
ts = now.strftime("%Y-%m-%dT%H:%M:%S.%f") + now.strftime("%z")
5791

@@ -123,7 +157,9 @@ def remote_logging() -> None:
123157
f"{dag_run_id_root_url}",
124158
headers=headers,
125159
).json()
126-
if prefix_is_matched(tasks, dag_run_id_root_url, headers, required_prefix):
160+
if prefix_is_matched(
161+
tasks, dag_run_id_root_url, headers, required_prefix, airflow_version
162+
):
127163
break
128164
time.sleep(10)
129165
loop += 1
@@ -145,7 +181,7 @@ def remote_logging() -> None:
145181
opts = parser.parse_args()
146182

147183
if opts.airflow_version and not opts.airflow_version.startswith("2."):
148-
remote_logging()
184+
remote_logging(opts.airflow_version)
149185
else:
150186
# should not happen as we are using airflow-latest
151187
print("Remote logging is not tested for version < 3.x!")

0 commit comments

Comments
 (0)