Connect orchestrators, transformations, streaming systems, and custom producers.
Use runtime events when a system can report what actually ran. Add declared artifacts and static analysis to fill gaps without overriding stronger evidence.
Connect Airflow to see observed DAGs and tasks and associate task execution with warehouse lineage. Embrasure uses Airflow's official OpenLineage provider. You do not need an Embrasure package, callback, or change to your DAG code.
Open Connections → Other, then select Add Airflow.
Production Airflow.Create a separate connection for each Airflow deployment. Embrasure generates a unique OpenLineage namespace and a connection-scoped token so DAGs with the same name remain distinct across deployments.
Add the official provider to the same Python environment or container image as Airflow:
pip install apache-airflow-providers-openlineageUse a provider version compatible with your Airflow version. Redeploy or restart the Airflow scheduler and workers after installing it.
Copy the two environment variables shown by Embrasure immediately after creating the connection. The token is displayed only once.
The generated values have this structure:
export AIRFLOW__OPENLINEAGE__NAMESPACE='<generated namespace>'
export AIRFLOW__OPENLINEAGE__TRANSPORT='{"type":"http","url":"https://api.embrasure.ai","endpoint":"api/v1/airflow/<connection-id>/lineage","auth":{"type":"api_key","apiKey":"<connection token>"}}'Set both variables for the scheduler and workers, then restart them. Store the token with your normal Airflow secrets. If it is lost or exposed, generate a new token from the connection in Embrasure and replace the transport configuration.
Run a DAG normally. The provider emits OpenLineage events automatically. Embrasure creates the DAG and task records when those events arrive and adds table lineage when an event includes datasets that match a connected catalog.
Return to Connections → Other and open the Airflow connection.
If no events arrive, confirm that the provider is installed in the running Airflow environment, both variables are available to the scheduler and workers, and the processes were restarted. Airflow task logs will also show failed OpenLineage deliveries.
Dataproc can report lineage without the listener through Google Data Lineage; configure that on the cloud and warehouses page. To send events directly from any Spark runtime, use the OpenLineage listener. Its transport configuration is the same on every platform:
spark.extraListeners=io.openlineage.spark.agent.OpenLineageSparkListener
spark.openlineage.transport.type=http
spark.openlineage.transport.url=https://api.embrasure.ai
spark.openlineage.transport.endpoint=/api/v1/lineage?workspace_id=WORKSPACE_ID&connector_id=CONNECTOR_ID
spark.openlineage.transport.auth.type=api_key
spark.openlineage.transport.auth.apiKey=EMBRASURE_API_TOKEN
spark.openlineage.namespace=spark-productionWhat differs by platform is how the listener reaches the classpath:
openlineage-spark jar on the classpath, for example through --extra-jars, --packages, or a bootstrap action.Flink and other runtime producers can send standard OpenLineage events to the same lineage receiver.
Upload target/manifest.json after dbt compile or dbt build:
: "${EMBRASURE_LINEAGE_ACQUISITION_ID:?set a unique acquisition ID}"
jq --arg workspace "$WORKSPACE_ID" \
--arg connector "$CONNECTOR_ID" \
--slurpfile manifest target/manifest.json \
'{workspace_id:$workspace, connector_id:$connector, manifest:$manifest[0], completeness:"complete"}' \
> /tmp/embrasure-dbt-manifest.json
curl --fail-with-body --request POST \
--url https://api.embrasure.ai/v1/lineage/dbt/manifest \
--header "Authorization: Bearer $EMBRASURE_API_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: dbt-$BUILD_ID" \
--data-binary @/tmp/embrasure-dbt-manifest.jsonUse complete only for the exact project and connector scope. Use a new idempotency key for each acquisition and reuse it only to retry identical bytes.
Run the project export as the baseline: it captures the complete declared project for one environment, including models that did not run, and maps each virtual model name to its physical snapshot so other evidence resolves to the right asset. Then add runtime events for executed-run evidence, which carries more authority than declarations when both exist for the same edge.
Export the project after SQLMesh applies the target environment, then submit the rendered project to POST /v1/lineage/sqlmesh/project. Run the exporter with the same Python interpreter that runs SQLMesh, after sqlmesh plan --auto-apply or your normal deployment step. It needs only the standard library and your existing SQLMesh install.
Download the version pinned to the embrasure.sqlmesh-project@v1 export schema into your SQLMesh project:
curl --fail --location \
--output embrasure_sqlmesh_export.py \
https://raw.githubusercontent.com/EmbrasureAI/embrasure/67665401b7bb08d49d4912f9d65d8204fe847c39/scripts/sqlmesh/embrasure_sqlmesh_export.py
mkdir -p target
python embrasure_sqlmesh_export.py \
--project . \
--environment prod \
--output target/embrasure-sqlmesh-project.jsonThe exporter resolves environment-specific physical snapshot names from SQLMesh state. Embrasure keeps each virtual model name as the stable asset identity and records its physical snapshot as an alternate identifier. If state is unavailable, the exporter warns on stderr. Virtual table lineage still imports, but physical-name merging is unavailable.
Wrap the export with its workspace, connector, and project identities, then upload it:
jq --arg workspace "$WORKSPACE_ID" \
--arg connector "$CONNECTOR_ID" \
--slurpfile project target/embrasure-sqlmesh-project.json \
'{workspace_id:$workspace, connector_id:$connector, project_id:"analytics-sqlmesh", completeness:"complete", project:$project[0]}' \
> /tmp/embrasure-sqlmesh-request.json
curl --fail-with-body --request POST \
--url https://api.embrasure.ai/v1/lineage/sqlmesh/project \
--header "Authorization: Bearer $EMBRASURE_API_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: sqlmesh-$EMBRASURE_LINEAGE_ACQUISITION_ID" \
--data-binary @/tmp/embrasure-sqlmesh-request.jsonUse complete only for an entire project in one environment. The route accepts partial or complete, honors Idempotency-Key, and returns the standard lineage delivery receipt. Set the acquisition ID to a unique per-run value, such as $GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT in GitHub Actions. Every acquisition needs a new key, including a return to previously uploaded content. Reuse a key only to retry the same request.
Rendered SQL supplies column mappings only when every read matches a declared dependency. Python models and models without rendered SQL keep table-level dependencies without guessed column lineage. See the SQLMesh project API reference for the request contract.
The community-maintained sqlmesh-openlineage package emits a run event per executed model evaluation, adding executed-run evidence on top of the export. It is not maintained by Embrasure, so pin and test its version with your SQLMesh release; it requires Python-based SQLMesh configuration. If you cannot install third-party instrumentation, project export remains the fully supported path.
Install the package, then enable it in config.py before creating the SQLMesh Config:
pip install sqlmesh-openlineageimport sqlmesh_openlineage
sqlmesh_openlineage.install()Use the bare API origin because OpenLineage clients append /api/v1/lineage. Authenticate with a workspace-scoped personal access token that has write scope, and keep the namespace stable for one deployment:
export OPENLINEAGE_URL="https://api.embrasure.ai"
export OPENLINEAGE_NAMESPACE="analytics-sqlmesh-prod"
export OPENLINEAGE_API_KEY="$EMBRASURE_WORKSPACE_SCOPED_TOKEN"Create the token first
In Embrasure, open Access Embrasure → API → Personal access tokens and create a PAT for the target workspace. The user who creates it must have editor or administrator access for lineage ingestion. Read the authentication guide for setup and storage details.
Run sqlmesh run normally. See the lineage receiver for authentication and dataset resolution.
Connect Fivetran in the app: open Settings → Integrations → Fivetran, enter a Fivetran API key and secret, and validate them. Then map each Fivetran connection to its Embrasure source and destination connectors and enable it. Embrasure currently syncs Postgres-to-BigQuery replication lineage, recording connector assets, sync runs, table mappings, and enabled column mappings.
Import DataHub exports at POST /v1/lineage/datahub. For applications and APIs, send standard OpenLineage datasets, jobs, runs, and optional columnLineage facets to the lineage receiver.
Use stable, case-sensitive namespaces and names. Both endpoints must resolve to cataloged objects before an edge appears in the served graph.