Skip to content

Commit 0610488

Browse files
committed
fix: don't split nodes based on different parents (even though its the same)
1 parent 1f162c5 commit 0610488

1 file changed

Lines changed: 20 additions & 23 deletions

File tree

stacks/openlineage/airflow.yaml

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -168,29 +168,25 @@ data:
168168
self.openlineage_inputs = openlineage_inputs or []
169169
self.openlineage_outputs = openlineage_outputs or []
170170
171-
def _link_spark_run_to_this_task(self, context):
172-
# CLEAN-LINEAGE KNOB #1: hand the Spark job this task's OpenLineage run identity via
173-
# `spark.openlineage.parent*`. That makes Spark report its own run as a CHILD of this Airflow
174-
# task (so the real Spark job is reachable from the DAG in Marquez) and, crucially, gives the
175-
# Spark run a real parent name instead of the `unknown` OpenLineage falls back to when it
176-
# can't resolve one at listener startup.
177-
try:
178-
from airflow.providers.openlineage.plugins.macros import (
179-
lineage_job_name,
180-
lineage_job_namespace,
181-
lineage_run_id,
182-
)
183-
184-
ti = context["task_instance"]
185-
conf = self.application_file["spec"]["sparkConf"]
186-
conf["spark.openlineage.parentJobNamespace"] = lineage_job_namespace()
187-
conf["spark.openlineage.parentJobName"] = lineage_job_name(ti)
188-
conf["spark.openlineage.parentRunId"] = lineage_run_id(ti)
189-
except Exception as e: # never fail the task just because linking didn't work
190-
self.log.warning("Could not set OpenLineage parent run on the SparkApplication: %s", e)
171+
# CLEAN-LINEAGE KNOB #1: do NOT hand the Spark job this task's OpenLineage run identity via
172+
# `spark.openlineage.parent*`. It is tempting (it would nest the Spark run under this Airflow
173+
# task), but it actively BREAKS the Spark lineage in Marquez 0.51.x (explained below).
174+
#
175+
# Why: Spark correctly emits ONE application job named `orders_by_nation` (bare) carrying a
176+
# parent facet, and its SQL children reference that same bare parent. But Marquez renames any
177+
# job that has a parent facet to `{parentJobName}.{jobName}` UNLESS the name already starts
178+
# with the parent. The SQL jobs (`orders_by_nation.<cmd>.<table>`) already do, so they're left
179+
# alone; the application job (`orders_by_nation`) does not start with its parent
180+
# (`openlineage_demo.spark_orders_by_nation`), so Marquez stores it as
181+
# `openlineage_demo.spark_orders_by_nation.orders_by_nation` while the children still point at
182+
# bare `orders_by_nation` -> the one run splits into two app nodes and the chain breaks.
183+
#
184+
# Marquez draws only job<->dataset edges (never job->job parent edges), so the parent facet buys
185+
# no visible edge anyway. Airflow<->Spark is stitched via shared DATASET identities instead, in
186+
# get_openlineage_facets_on_complete (KNOB #2). `spark.openlineage.appName` (KNOB #3, in the
187+
# SparkApplication) still pins a stable, non-`unknown` job name.
191188
192189
def execute(self, context: "Context"):
193-
self._link_spark_run_to_this_task(context)
194190
hook = KubernetesHook(conn_id=self.kubernetes_conn_id)
195191
name = self.application_file["metadata"]["name"]
196192
self.log.info("Creating SparkApplication %s ...", name)
@@ -282,8 +278,9 @@ data:
282278
"spark.openlineage.transport.type": "http",
283279
"spark.openlineage.transport.url": "http://marquez:5000",
284280
"spark.openlineage.namespace": "spark-openlineage-demo",
285-
# parentJobNamespace/parentJobName/parentRunId are injected at task runtime by the
286-
# operator (see _link_spark_run_to_this_task) so they carry this run's real identity.
281+
# NB: spark.openlineage.parent* is deliberately NOT set here or at runtime — see
282+
# CLEAN-LINEAGE KNOB #1 above (it triggers a Marquez job-rename that splits the
283+
# Spark app node).
287284
},
288285
"volumes": [
289286
{"name": "script", "configMap": {"name": "spark-openlineage-job"}},

0 commit comments

Comments
 (0)