Learning Platform
Глоссарий Troubleshooting
Урок 02.04 · 22 мин
Средний
dbt_project_evaluatorlintingDAGtesting coveragebest practices

dbt_project_evaluator — автоматическая проверка структуры

Всё, что мы обсуждали в прошлых трёх уроках — medallion, naming, YAML organization — теряет смысл, если их никто не проверяет.

Тестирование качества данных с dbt — governance-угол На команде из 5 человек через год вы получите 50 моделей, нарушающих direction-rule, 30 моделей без description, 15 моделей с одинаковыми именами в разных слоях. Lint-в-CI решает эту проблему.

Главный инструмент для этого в dbt-экосистеме — dbt_project_evaluator от dbt Labs. Это пакет, который запускает ~50 проверок на ваш проект и репортит нарушения как обычные dbt-тесты. Этот урок — про то, как его поставить и какие правила реально важные.

Зачем нужен evaluator

dbt-проект — это код + декларации, и оба они могут разойтись с best practices. Примеры:

  • Кто-то добавил ref('fct_orders') в staging-модель — нарушение direction-rule.
  • Кто-то создал mart-модель без description — техдолг для downstream.
  • Кто-то материализовал staging как table (вместо view) — дорогой и неоптимальный.
  • В модели нет ни одного теста — критичная таблица без проверок.
  • Модели в одной папке имеют разные tags — нарушение consistency.

Найти такое глазами на 200 моделях невозможно. Evaluator делает это автоматически на каждом dbt-run или в CI.

Что проверяет evaluator

Эти 5 категорий покрывают 90% типичных проблем production-проекта. Evaluator репортит нарушения как обычные dbt test failures.

ModelingDAG-нарушения: staging ссылается на mart, циклы, fanouts, ребусы. Проверяет физическую структуру зависимостей
TestingПокрытие тестами: модели без тестов, columns без not_null, primary key без unique
DocumentationПокрытие документацией: модели без description, columns без description, missing parent description
StructureNaming и organization: staging без stg_ префикса, marts без fct_/dim_, файлы YAML в неправильном месте
PerformanceОптимизации: staging как table вместо view, multi-step joins без intermediate, отсутствующие partitioning hints
GovernanceДоступы и контракты: модели без owner-меты, missing contracts на public моделях

Установка

Evaluator — обычный dbt-пакет. В packages.yml:

packages:
  - package: dbt-labs/dbt_project_evaluator
    version: 0.14.0

Затем:

dbt deps

Это добавляет 50+ моделей в dbt_packages/dbt_project_evaluator/, которые при запуске анализируют ваш проект и пишут результаты в схему dbt_project_evaluator.

Конфигурация в dbt_project.yml

В корне проекта добавляем:

# dbt_project.yml
vars:
  dbt_project_evaluator:
    # схема для evaluator-таблиц (default: dbt_project_evaluator)
    target_schema: dbt_project_evaluator
    
    # отключить специфические правила, если они вам не подходят
    disabled_tests:
      - fct_test_directories
      - fct_test_coverage

Из коробки включены все 50+ правил. На реальных проектах вы обычно отключаете 5-10 правил, которые не применимы (например, ваш проект не использует exposures — отключаете правила про exposures).

Запуск

dbt build --select package:dbt_project_evaluator

Эта команда запускает evaluator-модели (они анализируют ваш проект) и затем evaluator-тесты (они проверяют, что нарушений нет). Если есть нарушения — тесты падают с понятным сообщением.

Альтернативно — запускать только тесты:

dbt test --select package:dbt_project_evaluator

Главные правила

В пакете 50+ правил. Не все одинаково важные. Я разделю их на три группы — must-have, nice-to-have, и optional.

Must-have rules (критичные)

  1. fct_direct_join_to_source — staging должен быть единственным слоем, который join’ится с source. Если intermediate или mart напрямую читает source — нарушение medallion-архитектуры.

  2. fct_model_fanout — если одна модель имеет 8+ downstream-моделей, это часто симптом «god-model»: она делает слишком много, её надо разбить.

  3. fct_multiple_sources_joined — если одна staging-модель join’ит две разные sources, это нарушение «1 staging = 1 source».

  4. fct_rejoining_of_upstream_concepts — модель D зависит от B и C, оба зависят от A. Это диамант в DAG, обычно симптом того, что нужно одно общее intermediate.

  5. fct_root_models — модели без upstream-моделей (нет ref/source). Часто это случайный baked-in seed или забытый кусок кода.

  6. fct_undocumented_models — модели без description в YAML. На каждой mart-модели обязательно. На staging — желательно. На intermediate — опционально.

  7. fct_missing_primary_key_tests — модель имеет колонку с именем *_id (вероятный primary key), но на ней нет unique+not_null тестов.

Nice-to-have rules

  1. fct_model_naming_conventions — staging начинается с stg_, marts с fct_/dim_. Хорошее правило, но иногда команда хочет другой convention.

  2. fct_test_coverage — общий % покрытия тестами. Если меньше 50% — техдолг.

  3. fct_documentation_coverage — общий % покрытия description. Если меньше 80% на mart-моделях — техдолг.

  4. fct_unused_sources — sources в _sources.yml, на которые никто не ссылается. Часто — забытые после рефакторинга.

  5. fct_chained_views_dependencies — длинные цепочки view -> view -> view -> mart. На больших данных это перформанс-проблема.

Optional rules

Правила, которые зависят от ваших conventions:

  • fct_test_directories — staging-тесты только в staging/ директории, etc.
  • fct_sources_without_freshness — все sources имеют freshness threshold.
  • fct_marts_or_intermediate_dependent_on_source — никогда не ref(‘source’).

Включать или нет — решение команды. Старт лучше с must-have, потом добавлять остальное по мере зрелости проекта.

Пример сообщения об ошибке

$ dbt test --select package:dbt_project_evaluator

Failure in test fct_direct_join_to_source (models/marts/finance/_finance__models.yml)
  Got 2 results, configured to fail if != 0

  compiled Code at target/compiled/.../fct_direct_join_to_source.sql

  in event:
    parent_resource = analytics.raw.stripe.charges
    child_resource = analytics.marts.finance.fct_orders

Done. PASS=12 WARN=0 ERROR=1 SKIP=0 TOTAL=13

Здесь evaluator говорит: fct_orders напрямую читает source('stripe', 'charges'), минуя staging-слой. Нарушение direction-rule.

Чтобы починить: создайте stg_stripe__charges (если ещё нет) и измените fct_orders на ref('stg_stripe__charges').

Интеграция в CI

Главная польза evaluator — запуск в CI на каждом PR. В GitHub Actions (модуль 13 разберём подробнее):

# .github/workflows/ci.yml
- name: Run dbt project evaluator
  run: |
    dbt deps
    dbt build --select package:dbt_project_evaluator --target ci

Если evaluator упал — PR не мерджится. Это даёт жёсткий контроль качества структуры на уровне процесса, а не «когда заметят».

TIP

Если у вас уже большой legacy-проект и evaluator на нём падает с 200 нарушениями — не пытайтесь починить всё сразу. Вместо этого: (1) включите evaluator в CI с severity: warn, не error; (2) сделайте baseline снапшот нарушений; (3) на каждом PR проверяйте, что число нарушений не увеличивается; (4) постепенно фиксите legacy. Через 3-6 месяцев перейдёте на severity: error.

DuckDB-специфика

  • Evaluator работает на DuckDB полностью без проблем.
  • На больших проектах (500+ моделей) evaluator-модели могут использовать много памяти. На DuckDB добавьте memory_limit: '8GB' в profiles.yml.
  • Некоторые правила (fct_partitioning_*) специфичны для Snowflake/BQ и на DuckDB просто не активны.

Альтернативы

dbt_project_evaluator — не единственный инструмент. Есть ещё:

  • sqlfluff с dbt templater — линт SQL-синтаксиса, не структуры (модуль 12).
  • dbt-checkpoint — pre-commit hooks для dbt (модуль 12). Часть проверок пересекается.
  • Custom singular tests — можно написать свои тесты на стуктуру, но это пере-изобретение.

Лучшая комбинация на production: dbt_project_evaluator + sqlfluff + dbt-checkpoint в pre-commit. Полный стек разберём в модулях 12-13.

Production gotchas

1. Слишком много правил включено сразу

Если вы включаете все 50 правил на проект, который никогда не проверялся, получите 500+ failures. Команда демотивируется. Стартуйте с 5-10 must-have правил, добавляйте по одному правилу в неделю.

2. Disabled tests без commit-сообщения «почему»

Когда вы отключаете правило в disabled_tests, обязательно оставляйте комментарий-обоснование:

vars:
  dbt_project_evaluator:
    disabled_tests:
      # Отключено 2026-03-15 — у нас legacy intermediate без префикса int_
      # из-за миграции с старого проекта. План: переименовать к Q3 2026.
      - fct_model_naming_conventions

Без комментариев через полгода никто не помнит, почему правило выключено.

3. Evaluator на каждом dbt run — медленно

Полный запуск evaluator — это 50+ моделей, на больших проектах это 5-10 минут. Не запускайте на каждом локальном dbt build. Запускайте только в CI или как отдельную команду перед PR.

4. Тесты warn vs error

В CI часть evaluator-тестов имеет severity: warn (документация, performance), часть — severity: error (DAG-нарушения). Не путайте — warn не блокирует CI, error блокирует. Если вы хотите блокировать PR на missing description — повышайте severity до error явно.

Попробуй сам

В своём проекте:

  1. Добавьте dbt_project_evaluator в packages.yml, запустите dbt deps.
  2. Запустите dbt build --select package:dbt_project_evaluator и посмотрите список нарушений.
  3. Выберите 3 самых критичных правила (DAG-direction, primary key tests, documentation на marts) — почините нарушения по ним.
  4. Отключите 2-3 правила, которые вам не подходят (например, если у вас нет exposures).
  5. Запустите ещё раз — убедитесь, что критичные правила теперь pass.

Альтернативные пакеты структурного аудита

Помимо dbt_project_evaluator есть dbt-meta-testing (Tubular) для проверки meta-полей на моделях и сорцах. Если ваша команда требует, чтобы у каждой модели был owner в meta — этот пакет проверяет наличие. Но он менее популярен и покрывает меньше правил.

В реальной работе 90% команд останавливаются на dbt_project_evaluator — он закрывает базовые потребности.

Проверка знанийKnowledge check
Команда настроила dbt_project_evaluator в CI с severity error на все 50 правил. Через две недели команда жалуется, что PR не мерджатся, потому что evaluator всегда красный. Что сделать дальше — кроме 'отключить evaluator'?
ОтветAnswer
Проблема не в evaluator, а в подходе к его адаптации в существующий проект с techдебтом. Правильная последовательность шагов: первое — сделать audit нарушений и разбить их на категории — критичные (DAG-нарушения, missing primary key tests), важные (documentation gaps), и nice-to-have (perf hints). Второе — для каждого правила установить severity осознанно: критичные — error, важные — warn, nice-to-have — отключить или warn. Третье — построить baseline: текущее число warn-нарушений зафиксировать, и в CI добавить проверку 'число warn не увеличилось'. Это останавливает регрессии, не блокируя PR. Четвёртое — выделить инженерное время (1-2 дня в спринт) на починку legacy нарушений, начиная с критичных. Через 4-6 спринтов проект приходит в порядок. Главный принцип — нельзя включать lint на legacy кодовую базу с 'все правила = error', потому что вы превращаете уже работающий проект в систему 'ничего не мерджится'. Правильный путь — error на новый код, warn на старый, постепенная миграция.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. Какое правило dbt_project_evaluator стоит включать в первую очередь на новом проекте?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4