💡

dbt macro tips advent calendar 2022 day 12 - meta

2022/12/12に公開

便利なデータ変換ツールである dbt の中のmacroに関するtipsを書いていく dbt macro tips Advent Calendar 2022 12日目です。

dump_fail_testは便利な半面、運用上困った点があります。
それは、問答無用ですべての失敗したテストの結果をdumpする点にあります。
他にも、カラム数が多い場合表示しきれないという問題もあります。

さて、そんな問題を解決するために、 dump_fail_test が表示する個々のtestに対して何かしらのメタ情報を付与して、動作を制御したいですね。

そんなときに役に立つのがmetaです。

meta

https://docs.getdbt.com/reference/resource-configs/meta

meta自体はconfigの一部で、汎用的にいろいろなメタ情報を追加する事ができるようになっています。
これはmodelにもtestにも設定できるので、カラムやモデル、テストの情報を豊富にするのに役に立ちます。

例えば以下のような記述をしてみましょう。

models/example/schema.yml
version: 2

models:
  - name: my_first_dbt_model
    description: "A starter dbt model"
    columns:
      - name: id
        description: "The primary key for this table"
        tests:
          - unique
          - not_null:
              config:
                meta:
                  sensitive: true

  - name: my_second_dbt_model
    description: "A starter dbt model"
    columns:
      - name: id
        description: "The primary key for this table"
        tests:
          - unique
          - not_null

このように記述すると、マニフェストファイルには以下のように記述されます。

target/manifest.json
{
  "metadata": {...省略...},
  "nodes": {
    ...省略...
    "test.macro_tips_advcal.not_null_my_first_dbt_model_id.5fb22c2710": {
      ...省略...
      "config": {
        "enabled": true,
        "alias": null,
        "schema": "dbt_test__audit",
        "database": null,
        "tags": [],
        "meta": {
          "sensitive": true
        },
        "materialized": "test",
        "severity": "ERROR",
        "store_failures": null,
        "where": null,
        "limit": null,
        "fail_calc": "count(*)",
        "warn_if": "!= 0",
        "error_if": "!= 0"
      },
      "meta": {
        "sensitive": true
      },
      ...省略...
    },
    ...省略...
  },
  ...省略...
}

マニフェストファイルに記載されているということは、 graph コンテキスト変数を使ってこの情報を取得できるということでもあります。

先日のdump_fail_testを少し改造してみましょう

macros/dump_fail_test.sql
{%- macro dump_fail_test(results) %}

  {%- if execute %}
    {%- do log("========== Begin Failure Tests  ==========", info=True) %}
        {% for res in results -%}
            {%- if res.node.unique_id.startswith('test.') and res.node.language == 'sql' and res.status == 'fail' %}
                {%- set sql = res.node.compiled_code %}
                {%- do log("["~res.node.unique_id~"]>\n"~(sql | trim), info=True) %}
                {%- if 'sensitive' in res.node.meta and res.node.meta['sensitive'] %}
                    {%- do log("this test is sensitve. no dump.",info=True) %}
                {%- else %}
                    {%- do run_query(sql).print_table(max_rows=20, max_columns=6,max_column_width=None) %}
                {%- endif %}
            {%- endif %}
        {%- endfor %}
    {%- do log("========== End Failure Tests ==========", info=True) %}
  {%- endif %}

{%- endmacro %}
diff --git a/macros/dump_fail_test.sql b/macros/dump_fail_test.sql
index 6c8130f..21ef1b2 100644
--- a/macros/dump_fail_test.sql
+++ b/macros/dump_fail_test.sql
@@ -3,10 +3,14 @@
   {%- if execute %}
     {%- do log("========== Begin Failure Tests  ==========", info=True) %}
         {% for res in results -%}
            {%- if res.node.unique_id.startswith('test.') and res.node.language == 'sql' and res.status == 'fail' %}
                 {%- set sql = res.node.compiled_code %}
                 {%- do log("["~res.node.unique_id~"]>\n"~(sql | trim), info=True) %}
-                {%- do run_query(sql).print_table(max_rows=20, max_columns=6,max_column_width=None) %}
+                {%- if 'sensitive' in res.node.meta and res.node.meta['sensitive'] %}
+                    {%- do log("this test is sensitve. no dump.",info=True) %}
+                {%- else %}
+                    {%- do run_query(sql).print_table(max_rows=20, max_columns=6,max_column_width=None) %}
+                {%- endif %}
             {%- endif %}
         {%- endfor %}
     {%- do log("========== End Failure Tests ==========", info=True) %}

testのmetaを確認して、sensitiveという項目がtrueであれば、run_queryによるdata dumpをせずにSQLを表示するのみに留めるように変更しました。

metaを活用することで、macro中で様々な制御の設定が可能になりますので、色々便利に使ってみるのもありだとは思います。


13日目は pre-hookとpost-hookについて書こうと思います。

Discussion