MackerelでSelf-hosted dbt Fusion(preview)の監視をやってみる

こんにちは、グループ情報部の@mashiikeです。
この記事は Mackerel Advent Calendar 2025dbt Advent Calendar 2025 の7日目の記事です。

qiita.com
qiita.com

はじめに

この記事は、2つのAdvent Calendarにまたがった記事となるので、それぞれについて簡単に説明します。

dbt Fusion

www.getdbt.com
dbt は、データウェアハウス上のデータを「SQL+コード」で変換・整形・モデリングするOSSのツールです。分析用テーブルの整形や集約、履歴テーブルの作成などを、SQLで記述し、依存関係を解決しながら実行してくれます。 そして dbt Fusion は、その dbt の“次世代エンジン”です。Rust 製になって高速化・開発体験の改善がされていて、「ちょっとしたSQLのチェック」や「クエリの構造確認」などを、DWHに実行する前にローカルで軽くできるようになっています。

ざっくり一言で言うと、dbt Fusionはデータパイプラインを構築するアプリケーションの一つとなります。

Mackerel

ja.mackerel.io
Mackerel は、株式会社はてなが提供する 日本製のサーバ監視サービスです。『育てる監視』という言葉がコンセプトにあり、監視系のサービスの中では凄くシンプルなのが魅力的です。

最近では、 OpenTelemetry を使った APM/トレース機能にも対応しており、アプリケーションの内部動作や分散システムでの処理経路まで可視化できるようになっています。これにより、単なるホスト監視にとどまらず、モダンなマイクロサービスやクラウド環境のトレースにも対応可能です。

ざっくり一言で言うと、MackerelはOpenTelemetryに対応した監視サービスの一つとなります。

dbt FusionをSelf-hostedで試してみたんだが、いい感じに監視したい。

さて、記事の本題に入ります。 dbt には、dbt platform(旧dbt Cloud) というサービスがあり、dbt platformにはパイプラインの実行状況を可視化するUIがついているため、dbt Cloudを使ってる分には監視で困ることはないでしょう。
しかし、様々な事情により、dbtをSelf-hostedで運用したい場合はあります。
弊社でも、現行版であるdbt CoreをSelf-hostedで運用しているケースがあり、dbt FusionがGAされた場合もSelf-hostedで運用する可能性が十分にあります。 そこで、現在Preview版として提供されているdbt FusionをSelf-hostedで試してみました。

手始めに、ローカルで dbt init をすると、dbt Fusionの場合はサンプルプロジェクトが作成されます。
サンプルプロジェクトは以下のようなパイプラインになっています。

dbt Fusionのサンプルプロジェクトの依存関係図

dbtはこのような依存関係を考慮しながら、各SQLを実行していて行ってくれます。
※今回は監視が主題なので、必ずテストが失敗するモデル dummy を追加してます。

次に、以下のようなDockerfileを作成して、Google CloudのArtifact Registryにプッシュし、Cloud Run Jobsで定期実行するようにしました。

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    tzdata \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

ENV SHELL=/bin/bash
RUN curl -fsSL https://public.cdn.getdbt.com/fs/install/install.sh | bash

ENV PATH="/root/.local/bin:${PATH}"
COPY . .

ENV DBT_PROJECT_DIR=/app
RUN dbt deps

ENTRYPOINT ["dbt"]
CMD ["build"]
gcloud run jobs deploy dbt \
    --image=${IMAGE_PATH} \
    --region=${REGION} \
    --project=${PROJECT_ID} \
    --service-account=pipeline@${PROJECT_ID}.iam.gserviceaccount.com \
    --memory=2Gi \
    --cpu=1 \
    --max-retries=0 \
    --task-timeout=3600s \
    --set-env-vars=DBT_PROJECT_DIR=/app

定期実行の履歴。複数回失敗が見えるが、失敗モデル特定はここだけでは難しい。

この画面をみると、いくつか失敗してますね。
Google Cloud Monitoringを使えば、Cloud Run Jobsのコンテナが異常終了した場合にアラートを飛ばすことはできます。 しかし、どのモデルが失敗したのか? はログを読みに行かないとわかりません。 何かもうちょっと、いい感じに実行監視できないか? と思ったのが今回の記事の発端です。

dbt FusionからOpenTelemetryのログが出力できるので、Mackerelに送ってみた!

どうやって、監視しようと悩んでいたとき、dbtのCLIのhelpを見ると見つけてしまいました。 --otel-file-name というオプションがあり、OpenTelemetryのログを出力できるようです。

$ dbt --help   
dbt-fusion 2.0.0-preview.72: A fast and enriched dbt compiler and runner

Usage: dbt [OPTIONS] <COMMAND>

Commands:
  init           Initialize a new dbt project
  deps           Install package dependencies
  parse          Parse models
<中略>

      --log-path <LOG_PATH>
          Set 'log-path' for the current run, overriding 'DBT_LOG_PATH'
          
          [env: DBT_LOG_PATH=]

      --otel-file-name <OTEL_FILE_NAME>
          Set 'otel-file-name' for the current run, overriding 'DBT_OTEL_FILE_NAME'. If set, OTEL telemetry will be written to `$log_path/otel-file-name`
          
          [env: DBT_OTEL_FILE_NAME=]
<中略>
  -V, --version
          Print version

Use `dbt <COMMAND> --help` to learn more about the options for each command.

そこで、Claude Codeさんにお願いして小道具を作ってもらいました。

以前、私が作成した github.com/mashiike/jsonl-otel-forwarder のコードを参考にして、
 logs/otel.jsonl に出力されたログファイルをOpenTelemetryのCollectorに出力するOSSを書いてください。

そして、できたのがこちらです。 github.com

次のように設定ファイルを書いて config.yml

exporters:
  otlp:
    type: otlp
    endpoint: "https://otlp-vaxila.mackerelio.com"
    protocol: http/protobuf
    headers:
      Accept: "*/*"
      "Mackerel-Api-Key": "${MACKEREL_API_KEY:?MACKEREL_API_KEY is required}"

forward:
  default:
    resource:
      attributes:
        "service.name": "jaffle_shop"           # APM上のサービス名
        "deployment.environment": "production"  # 環境ラベル
    traces:
      attributes:
        - action: set
          when: |
            name.contains("Node evaluated") && attributes["dbt.phase"] == "EXECUTION_PHASE_RUN"
          key: "url.path"
          value_expr: attributes["dbt.unique_id"] # モデル/テストをパスに見立てる
        - action: set
          when: |
            name.contains("Node evaluated") && attributes["dbt.phase"] == "EXECUTION_PHASE_RUN"
          key: "http.request.method"
          value: "POST"                            # 仮想HTTPリクエスト化
        - action: set
          when: |
            name.contains("Node evaluated") && attributes["dbt.phase"] == "EXECUTION_PHASE_RUN"
          key: "http.response.status_code"
          value_expr: |
            status.code == "ERROR" ? 500 : 200     # 成否をHTTPステータスで表現
      exporters: [otlp]

※ tracesのattributesセクション、http関係の属性を追加しているのは、後述するMackerelのAPM機能で見やすくするための工夫です。

この小道具をラッパーコマンドとしてdbtを実行するとMackerelにテレメトリーが送られます。
もちろん、その他のOpenTelemetryサービスをお使いの方は送る先のエンドポイントを変えれば同様にできるはずです。

$ dbt-fusion-otel-forwarder --config config.yml -- dbt build

こうすることで、Mackerel上でSlack通知を設定していれば次のように通知が飛んできます。

MackerelからのSlack通知

アラートのリンクを飛んだ先のスクリーンショット

アラート詳細と紐づくトレース一覧。

リンクを飛んだ先にはトレースのSpanが並んでおり、失敗したNodeの下にはQueryExecutedのSpanがぶら下がっています。

失敗Node配下にQueryExecutedのSpanがぶら下がり、流れを追える。

このQueryExecutedのSpanの属性には、db.statementがあり、実行されたSQL文が格納されています。

Span属性のdb.statementから実行SQLを確認できる。
これで、スムーズに原因調査ができそうです。

APM機能でパイプラインのボトルネックも見える化できる

Mackerelには最近APM機能も追加されており、そのAPM機能でdbt Fusionで作成したパイプラインのボトルネックが簡単に可視化できました。

モデル・テスト毎の実行時間、エラー率が見られます。
Configファイルの紹介のときにしれっと、HTTP関係の属性を足していたのは、このモデル・テスト毎のパフォーマンスを仮想のHTTPリクエストとして扱うための工夫でした。

HTTP属性に寄せることでモデル/テスト単位の遅延・エラー率が一覧化。

また、実行しているSQLごとのパフォーマンスを見るタブもあって、こっちも便利です。

SQLごとの実行時間・エラー率ビュー。展開するとSQL全文を確認できる

省略表示だと、ほとんどdbtが挿入しているヘッダーコメントばかりですが、展開すると実際のSQL文が見られます。

まとめ

dbt FusionをSelf-hostedで運用する場合に、MackerelのAPM機能を使ってパイプラインの監視を行う方法を紹介しました。
dbt FusionはまだPreview版ですが、GAされた際にはSelf-hostedで運用・監視がちゃんとできそうなことは検証できたと思います。 また、今回Mackerelのトレース機能とAPM機能を使ってdbt Fusionの監視をしてみましたが、とても良い感じでした。
お試しで使ってみている感じ、使用感がとても良いので今からGAが楽しみです。
Mackerelは、シンプルなところが魅力と言いましたが、今回のケースとかはその魅力的な一例です。
本来であればサーバーのエンドポイント毎のパフォーマンスを見る画面を、使う側のちょっとした工夫でdbt Fusionのモデルごとのパフォーマンス分析に応用できたりします。
皆様も、サーバーに限らずにMackerelにテレメトリを送ってみてはいかがでしょうか? きっといい感じに表示する方法はあると思います。

カヤックでは、監視がすきなエンジニアも募集してるかもしれません。