dbtのtag利用をelementaryを使って統制する
やりたいこと
dbtの tags
はjobの制御として非常に強力だが、tagの種類自体は増えすぎないようにしたい。任意の文字列を設定できるので実装そのものは非常に簡単な一方、乱用されると似たようなtagが複数存在するようになったり、改修時のtagの修正漏れなどトラブルの元になってしまう。
特にdbtの経験が浅いジュニアメンバーはconfigに書かれているtagsが分かりやすく目立つので、そこから学習して新しいtagを書いてしまうこともあるが、複数のディレクトリ・ドメインにまたがる長大なデータパイプラインでない限りはディレクトリの指定やグラフオペレーターで十分jobを動かせることが大半だ。
そのため、設定するtagはなるべく最小限に抑えて、それぞれのtagの役割が利用者全員にすぐに伝わるような、統制が取れた状態を保ちたい。
とはいえ、管理台帳を作っても、そのうちメンテナンスされなくなることは目に見えており、都度Pull Requestで指摘するという方法もレビュアーが疲れるので、仕組みで制御したい。
どうやるか
コンセプトは以前書いたdbt project evaluatorの生成物を流用する方法と同じで、dbtのpackageがメタデータを収集する過程で生成するテーブルを使う。今回使うパッケージはelementaryというデータパイプラインの監視を目的としたもので、tagsの情報もテーブル化される。
elementaryの本来の監視機能を活用しようとすると、専用CLIなどのインストールも必要であるが、メタデータのテーブル化だけならdbt packageのインストールだけで良いので、dbt cloudユーザーでも導入できる。
実装
dbt elementary が取得したデータをテーブル化する
一番多いと思われる、モデルにタグを付けるケースを想定。サンプルとしてチュートリアルのモデルにタグを付けてみる。
my_first_dbt_model.sql
{{ config(
materialized='table',
tags = ['tag1', 'tag2'],
) }}
with source_data as (
以下略
my_second_dbt_model
{{ config(
materialized='table',
tags = ['tag3'],
) }}
select *
以下略
次に dbt run --select elementary
でelementaryが取得するデータをテーブル化すると、画像のような形でSTRING形式のtagsが取得できる。
tag一覧を取得するviewを作成する
生成されるデータはmodel単位なので、tag単位の一覧を作成する。同時に、それぞれのtagがどういう役割なのかを説明するdescriptionを書いたseedファイルも作っておくと良い。
タグの一覧を作成するsql
WITH
tag_list AS (
SELECT
tag,
STRING_AGG(alias
ORDER BY
unique_id
LIMIT
5) AS related_model_sample
FROM
{{ ref("dbt_models") }},
UNNEST(JSON_VALUE_ARRAY(tags)) AS tag
GROUP BY
1
),
output AS (
SELECT
*
FROM
tag_list
LEFT JOIN
{{ ref("seed_tag_description") }}
USING
(tag)
)
SELECT
*
FROM
output
出力結果
想定外のtagが追加された場合に失敗するテストを用意する
上に記載したsqlが作成するviewに対して、ymlにテストを記載する。
accepted_values
と、seedファイルの description
に新しいタグに関する情報を記載していないとテストに失敗するようになっている。
version: 2
models:
- name: metrics_dbt_metadata__dbt_tag_list
description: "List of dbt tags"
columns:
- name: tag
description: "dbt tag"
tests:
- unique
- not_null
- accepted_values:
values: ['tag1', 'tag2', 'tag3']
- name: description
description: "description of dbt tag"
tests:
- not_null
あとは dbt project evaluator と同様に、CIテストの中に組み込んでおくと、PR作成時に自動でチェックされるようになるので、意味もなくtagが追加されることがなくなり、増やす場合でもその必要性をPR上で議論しやすくなる。
他の任意の設定値が書けるmetaフィールドなども、同様の方法で管理できる。逆に、書いておいて欲しいメタデータがないことを検知して、テストで落とすといったことも工夫すればできそうである。
dbtはスキル要件が低く、ジュニアデータアナリストといったエンジニアスキルが少ない人でも容易に扱うことができる反面、利用者を広げていく場合は統制の取りにくさがどうしても発生してしまうので、こうしたレビュアーに負担を掛けない、仕組みを使った管理を増やしていくと、トラブルを減らせるだろう。
参考資料
dbt elementaryそのものの詳細な解説
Discussion