Интеграция с OpenLineage
DALI принимает события OpenLineage от runtime-инструментов (dbt, Spark, Airflow, Flink) и сливает их со статическим графом HOUND в единую YGG-базу. Результат: один граф, в котором видно и что описано в SQL, и что реально выполнялось в продакшне.
Двойной источник: HOUND + OpenLineage
При слиянии каждый узел получает два флага: static_observed (HOUND разобрал DDL) и runtime_observed (OL-событие зафиксировало выполнение). Если оба true — узел «известен в полной мере».
Пайплайн обработки события
Дедупликация
Сигнатура запроса, инвариантная к форматированию. Один и тот же SQL с разными отступами или регистром считается дублём и не создаёт лишних узлов в графе.
SQL-отпечатокЗапросы, отличающиеся только значениями констант в условиях, считаются одним шаблоном. Тысячи параметризованных запусков одного SELECT схлопываются в единый узел графа.
SQL-шаблонПри обходе графа один и тот же путь A→B может возникнуть по нескольким маршрутам. Дублирующиеся рёбра автоматически устраняются перед отправкой в LOOM.
Граф-дедупликацияДопарсинг SQL внутри OL-событий
OpenLineage-события от dbt и Spark часто содержат SQL-текст в SQLJobFacet. DALI извлекает этот SQL и передаёт его в HOUND для полноценного ANTLR4-разбора — точно так же, как если бы это был статический файл.
// OL-событие от dbt содержит SQL в facets:
{
"job": { "facets": {
"sql": { "query": "SELECT o.id, c.tier, o.amount * c.discount AS discounted_amount\n FROM stg_orders o JOIN stg_customers c ON o.customer_id = c.id" }
}},
"outputs": [{ "name": "orders_enriched", "facets": {
"columnLineage": {
"fields": {
"discounted_amount": {
"inputFields": [
{ "name": "stg_orders", "field": "amount" },
{ "name": "stg_customers", "field": "discount" }
]
}
}
}
}}]
}
// DALI: HoundJobParser.extractSql() → отправить в HOUND → DaliStatement-узел
// Результат: граф знает не только "discounted_amount ← amount + discount",
// но и полный AST, все промежуточные операции и связи с DDL-определениями таблиц.Поддерживаемые источники (producers)
Разметка в LOOM
После слияния каждый узел и ребро в YGG получают метку источника. LOOM визуализирует их по-разному.
origin: "static"Сплошная граница, 100% прозрачность. SQL разобран, в продакшне не наблюдался.
Сплошное реброorigin: "runtime"Пунктирная граница, 70% прозрачность. Реальное выполнение есть, DDL ещё не разобран.
Пунктирное/синее реброorigin: "both"Сплошная граница + ★ бейдж. Полная картина: и структура, и факт выполнения.
Сплошное + синее реброТранспорты
DALI сканирует директорию dali.ol.events-dir каждые 30 секунд. Обработанные → processed/, упавшие → failed/. Удобно для dbt/Spark с file transport.
POST /api/v1/lineage — стандартный OL-совместимый эндпоинт. Марquez-совместимый URL. Producer пушит напрямую без промежуточного файла.
Планируется при объёме >1К событий в день. Текущая архитектура рассчитана на файл/HTTP — достаточно для большинства on-premise инсталляций.
roadmap · v1.6+