hanxdatadog commented on code in PR #71793:
URL: https://github.com/apache/airflow/pull/71793#discussion_r4484678121


##########
task-sdk/src/airflow/sdk/execution_time/task_runner.py:
##########
@@ -1298,6 +1298,13 @@ def startup(msg: StartupDetails) -> 
tuple[RuntimeTaskInstance, Context, Logger]:
 
     with _airflow_parsing_context_manager(dag_id=msg.ti.dag_id, 
task_id=msg.ti.task_id):
         ti = parse(msg, log)
+
+    if conf.getboolean("logging", "dag_tags_in_logs", fallback=False) and 
ti.task.dag.tags:
+        # Nested under one key so free-form tags can't overwrite standard log 
fields.
+        bind_contextvars(
+            dag_tags={key: value for key, _, value in (tag.partition(":") for 
tag in ti.task.dag.tags)}

Review Comment:
   Fixed: `dag_tags` is now the sorted raw tag list (`["owner", "owner:x", 
"team:a", "team:b"]`), so nothing is dropped and the order doesn't depend on 
the hash seed. Added a test with tags sharing a key.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



##########
task-sdk/src/airflow/sdk/execution_time/task_runner.py:
##########
@@ -1298,6 +1298,13 @@ def startup(msg: StartupDetails) -> 
tuple[RuntimeTaskInstance, Context, Logger]:
 
     with _airflow_parsing_context_manager(dag_id=msg.ti.dag_id, 
task_id=msg.ti.task_id):
         ti = parse(msg, log)
+
+    if conf.getboolean("logging", "dag_tags_in_logs", fallback=False) and 
ti.task.dag.tags:
+        # Nested under one key so free-form tags can't overwrite standard log 
fields.
+        bind_contextvars(

Review Comment:
   Fixed: added `dag_tags` to `tiContextFields`, so it shows once in the 
preamble.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



##########
airflow-core/src/airflow/config_templates/config.yml:
##########
@@ -1008,6 +1008,17 @@ logging:
       type: string
       default: "filename,lineno"
       example: ~
+    dag_tags_in_logs:
+      description: |
+        Set to ``True`` to include Dag tags in a ``dag_tags`` structured field 
on task logs emitted

Review Comment:
   Fixed: the description now says only task-process lines carry the field, and 
names the supervisor's forwarded stdout/stderr and kill/abnormal-exit messages 
as not covered. Getting the tags to the supervisor would need them sent over 
comms, so I'd keep that out of this PR.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



##########
airflow-core/src/airflow/config_templates/config.yml:
##########
@@ -1008,6 +1008,17 @@ logging:
       type: string
       default: "filename,lineno"
       example: ~
+    dag_tags_in_logs:
+      description: |
+        Set to ``True`` to include Dag tags in a ``dag_tags`` structured field 
on task logs emitted
+        once the Dag has been parsed (log lines emitted during parsing itself 
cannot carry them).
+        Tags that contain a colon (e.g. ``env:prod``) are split into a 
key/value pair. Plain tags
+        (e.g. ``production``) map to an empty value. For example, tags 
``env:prod`` and ``production``
+        are logged as ``dag_tags={"env": "prod", "production": ""}``.
+      version_added: 3.4.0

Review Comment:
   Fixed: `version_added: 3.5.0`.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



##########
airflow-core/newsfragments/71793.feature.rst:
##########
@@ -0,0 +1 @@
+Added ``[logging] dag_tags_in_logs`` to optionally include Dag tags in a 
``dag_tags`` structured log field on task logs.

Review Comment:
   Fixed: dropped the newsfragment.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



##########
task-sdk/tests/task_sdk/execution_time/test_task_runner.py:
##########
@@ -7563,3 +7564,113 @@ def 
test_stats_tags_with_standalone_and_key_value_tags(create_runtime_ti):
         "task_id": "t",
         "run_type": "manual",
     }
+
+
+def _make_startup_details(make_ti_context, tags) -> tuple[StartupDetails, 
BaseOperator]:
+    """Build a StartupDetails/task pair for a Dag carrying the given tags."""
+    with DAG("logging_tagged_dag", tags=tags):
+        task = BaseOperator(task_id="t")
+
+    ti = TaskInstance(
+        id=uuid7(),
+        task_id="t",
+        dag_id="logging_tagged_dag",
+        run_id="c",
+        try_number=1,
+        dag_version_id=uuid7(),
+        queue="default",
+    )
+    what = StartupDetails(
+        ti=ti,
+        dag_rel_path="",
+        bundle_info=FAKE_BUNDLE,
+        ti_context=make_ti_context(),
+        start_date=timezone.utcnow(),
+        sentry_integration="",
+    )
+    return what, task
+
+
+def _startup_with_dag_tags(
+    mocked_parse, mock_supervisor_comms, make_ti_context, tags
+) -> tuple[dict, TaskInstance]:
+    """
+    Run startup() for a Dag carrying the given tags.
+
+    Returns the bound structlog contextvars alongside the TaskInstance used, 
so tests can assert
+    against ground-truth identifier values. Contextvars are cleared before 
returning so a leftover
+    binding can't leak into unrelated tests that run afterwards.
+    """
+    what, task = _make_startup_details(make_ti_context, tags)
+    mock_supervisor_comms._get_response.return_value = what
+    mocked_parse(what, "logging_tagged_dag", task)
+
+    clear_contextvars()

Review Comment:
   Fixed: removed the `clear_contextvars()` calls and import, and the ordering 
test reuses the helper.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @hanxdatadog before posting



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to