dbtのrun-operationの出力情報を制御する

背景: dbt run-operationは便利

dbtのサブコマンドであるrun-operationは結構便利で、標準のコマンドでサポートされていないようなオペレーションを簡単に実行することができる。例えば、以下のようなものは日常的に自分は利用している。

課題: 出力形式がちょっと微妙...

その他にはSQLの自動生成にも利用している。特定の条件でフィルタしたものをテーブル化するSQLを自動生成させる、といったことに仕事でも使っている。コマンドライン経由でも以下のように引数を渡せるため、使い勝手がよい。

dbt run-operation my_macro --args "{'arg1': 'ほげ', 'arg2': 'ふが'}"

自動生成させる際、出力ファイルをマクロ側で指定できないため、標準出力に吐かせることになる。

しかし、これは結構罠がある。dbtはコマンドを実行する際、以下のような出力をする。

17:31:59  Running with dbt=1.7.13
17:32:01  Registered adapter: bigquery=1.7.8

自動生成時はこの出力は結構邪魔である。この問題にどう対応すればいいのかコミュニティであまり見解はないような気がするが、dbtの公式のdbt-codegenだとtailコマンドを使って回避している。結構苦しい。

出力される行数が固定でも苦しいが、warningなどを出るように設定していると行数も固定できない。例えば、deprecation_dateを設定している場合、コマンドを走らせる度に以下のメッセージが出力されてしまい、自動生成の邪魔となってしまう。

17:32:04  [WARNING]: While compiling 'my_model_child': Found a reference to my_model_parent, which is slated for deprecation on '2024-05-31T00:00:00+09:00'. 

--log-level errorを設定するとwarningを黙らせることができるかと思ったが、そうすると自動生成したい内容はinfoで出力されるため、空ファイルができてしまう。困った...。

解決策: json形式で出力させ、jqで欲しい形にフィルタする

色々検討してみたが、--log-format jsonでjson形式で出力させ、欲しい形にjqでフィルタするのがよさそう、と自分の中で結論が出た。

dbt --no-use-colors --log-format json run-operation my_macro --args "{'arg1': 'ほげ', 'arg2': 'ふが'}" | \
  jq -r 'select(.info.level == "info" and .info.name == "JinjaLogInfo") | .info.msg' > example.sql