本記事は ZOZO Advent Calendar 2025 シリーズ 2 の 13 日目の記事です。
概要
「Source freshnessの結果もElementaryで通知できるの?」
dbtとElementaryでデータ監視をしていると、こういう疑問が出てきます。公式ドキュメントを見てもパッと分からなかったので、実際に検証してみました。
結論として、Source freshnessの結果もElementaryで管理・通知できます。ただし、Hourly実行など高頻度で運用する場合は重複通知に注意が必要です。
前提
本記事は以下の環境・知識を前提としています。
- dbt-core 1.9系
- elementary-data 0.16系
- Source freshnessを導入したい、または既に導入している
- 通知をElementary(edr monitor)に統一したい
Source freshness自体の詳細については公式ドキュメントを参照してください。
検証1: Source freshnessの結果はElementaryに保存されるか?
結論: YES
Elementaryの設定を有効にしていれば、Source freshnessの結果もElementaryのテーブルに保存されます。
有効化設定
dbtのバージョンによって設定方法が異なります。
dbt 1.8以上の場合
dbt_project.ymlで以下のフラグを設定します。
flags:
source_freshness_run_project_hooks: True
このフラグにより、Elementaryがdbt source freshnessの結果を他のテスト結果と同様に自動的に収集します。
dbt 1.8未満の場合
dbt source freshness実行後、edr monitor実行前に以下のコマンドを実行します。
edr run-operation upload-source-freshness --project-dir <path to your project>
注意点として、dbt source freshnessとupload-source-freshnessは同じマシンから実行する必要があります。
保存先テーブル
Source freshnessの結果は以下のテーブルに保存されます。
| テーブル名 | 内容 |
|---|---|
dbt_source_freshness_results |
freshnessチェックの結果(max_loaded_at、snapshotted_at、status等) |
dbt_invocations |
コマンド実行履歴 |
alerts_v2 |
アラート送信履歴(※公式ドキュメントでは「alerts関連ビュー」としか記載がないため、実環境で確認した結果です) |
実際にdbt_source_freshness_resultsテーブルを確認すると、以下のようなデータが保存されていました(一部マスク)。
主要カラムの意味については以下の通りです。(※公式ドキュメントでは記載がないため、推察となります)
| カラム | 意味 |
|---|---|
unique_id |
チェック対象のソーステーブルの識別子 |
max_loaded_at |
テーブルで検出された最新データのタイムスタンプ |
snapshotted_at |
freshnessチェックを実行した時刻 |
max_loaded_at_time_ago_in_s |
最新データが何秒前のものか(snapshotted_at - max_loaded_at) |
status |
チェック結果(pass / warn / error) |
warn_after |
警告を出す閾値 |
error_after |
エラーを出す閾値 |
passの例(正常):
| カラム | 値 |
|---|---|
| unique_id | source.my_project.my_source.my_table |
| max_loaded_at | 2025-11-25T03:40:01+00:00 |
| snapshotted_at | 2025-11-25T03:40:02+00:00 |
| max_loaded_at_time_ago_in_s | 0.26 |
| status | pass |
| warn_after | {"count": 1, "period": "hour"} |
| error_after | {"count": null, "period": null} |
warnの例(警告):
| カラム | 値 |
|---|---|
| unique_id | source.my_project.my_source.daily_table |
| max_loaded_at | 2025-11-24T16:26:15+00:00 |
| snapshotted_at | 2025-11-25T03:41:29+00:00 |
| max_loaded_at_time_ago_in_s | 40514.18(約11時間) |
| status | warn |
| warn_after | {"count": 1, "period": "minute"} |
| error_after | {"count": null, "period": null} |
passの例では最新データが0.26秒前なのでほぼリアルタイム更新、warnの例では約11時間前でwarn_afterの1分を大幅に超えているため警告になっています。
検証2: edr monitorで通知できるか?
結論: YES
通常のdbt testと同様に、edr monitorコマンドでSlackへ通知できます。
実行コマンド
# Source freshnessを実行
dbt source freshness
# Elementaryで通知
edr monitor --slack-token $SLACK_TOKEN --slack-channel-name your-alert-channel
通知例
Source freshnessでwarnが発生すると、以下のようにSlackへ通知されます。
Warning: your_table: 1 issues detected
Powered by Elementary
Test Warnings: 1
Test Warnings
⚠ Freshness exceeded the acceptable times on source "your-project.your_dataset.your_table"
検証3: Hourly実行で重複通知が発生しないか?
結論: 発生する可能性あり
ここが最も重要なポイントです。Source freshnessをHourlyで実行する場合、意図しない重複通知が発生する可能性があります。
問題のシナリオ
edr monitorはデフォルトで直近1日分(days_back: 1)のアラートを取得します。そのため、以下のような問題が発生します。
-
Daily実行でdbtモデルがエラー →
edr monitorで通知済み -
1時間後のHourly実行 →
edr monitorが同じエラーを再取得 - 同じアラートが再度Slackに通知される(重複)
さらに悪いケースとして、Hourlyは毎時実行されるので、Dailyで発生したエラーが最大24回重複通知される可能性があります。
[Daily 9:00] エラー発生 → 通知①
[Hourly 10:00] 同じエラーを検知 → 通知②(重複)
[Hourly 11:00] 同じエラーを検知 → 通知③(重複)
...
[Hourly 翌8:00] 同じエラーを検知 → 通知㉔(重複)
解決策: --suppression-interval
edr monitorの--suppression-intervalオプションを使用することで、重複通知を防げます。
edr monitor --suppression-interval 1
この設定により、同じアラートは指定時間(時間単位)以内に再通知されなくなります。
| 設定値 | 挙動 |
|---|---|
--suppression-interval 1 |
同じアラートは1時間以内に再通知されない |
--suppression-interval 24 |
同じアラートは24時間以内に再通知されない |
これにより、以下の問題が解消されます。
- Daily側で既に通知されたアラートは、Hourly側で重複通知されない
- Hourly同士の連続実行でも重複しない
実際に検証してみた
「本当にsuppression-intervalで抑制されるの?」と気になったので、実際に検証してみました。
検証方法
参照しているテーブルによるのですが、わざと絶対に検知に引っかかる設定(warn_after: 1 minute)を作り、3回連続で実行してみます。
freshness:
warn_after: {count: 1, period: minute}
1回目: 通常通り通知される
dbt source freshness
edr monitor --slack-channel-name your-channel --suppression-interval 1
→ Slack通知あり(期待通り)
2回目: suppressionで通知が抑制される
同じコマンドをもう一度実行します。
dbt source freshness
edr monitor --slack-channel-name your-channel --suppression-interval 1
ログに以下のメッセージが表示されました。
INFO — Update skipped alerts
→ Slack通知なし(期待通り、suppressionが効いている)
3回目: suppression-interval 0 で抑制を無効化
本当にsuppressionによる抑制なのか確認するため、--suppression-interval 0で実行してみます。
dbt source freshness
edr monitor --slack-channel-name your-channel --suppression-interval 0
→ Slack通知あり(期待通り、抑制が無効化された)
この検証により、--suppression-intervalが確実に動作していることを確認できました。
まとめ
検証して分かったことをまとめます。
- Source freshnessの結果もElementaryで一元管理できる
-
dbt_source_freshness_resultsテーブルに結果が保存される -
edr monitorコマンドでSlack通知も可能 - ただし、Hourly運用には
--suppression-intervalで重複通知対策が必要
Elementaryを使っていてSource freshnessを導入したい方の参考になれば幸いです。