はじめに
インターンで「 Terraform を使ってSLO Error Budget Burn Rate アラートを Datadog に導入する」タスクをいただきました。
実務での実践の前に、自分で実際にトレースを流し、Monitor・SLO・Burn Rateアラートを構築して挙動を確認する「予習」を行いました。この記事はその予習内容を記録したものです。
これからDatadogでSLO運用をコード管理(IaC)したい方の参考になれば幸いです。
この記事で学べること
- Terraformを用いたDatadog Monitor / SLO / Burn Rateアラートのコード化
- SLO Burn Rateアラートにおける Two-window alerting の仕組みとメリット
- DatadogとSlackの通知連携をTerraformで管理する方法
前提条件
- Terraformの基本的な操作(
init,plan,apply)ができること - SLI / SLO / Error Budget(エラー予算)の基礎概念を理解していること
- Datadogのアカウントがあること(無料トライアル利用可)
💡 サンプルコード
本記事で使用したコードの全容は、こちらのGitHubリポジトリに公開しています:
https://github.com/hirune05/datadog-slo-practice/tree/main
ディレクトリ構成
~/dev/sre-sample/
├── .gitignore
├── app/ # 監視対象のFastAPIアプリ
│ ├── main.py
│ └── requirements.txt
└── terraform/ # Terraformのコード
├── provider.tf
├── variables.tf
├── terraform.tfvars # gitignore対象
├── slo.tf
└── slo_alert.tf
事前準備:Datadog Agentの導入と認証キーの取得
💡 すでにAgentのインストールとAPI/Appキーの取得が完了している方は、次のセクションへ読み飛ばしてください。
Datadogがローカルマシンのメトリクスやアプリのトレースを収集するためには、データの仲介役となる Datadog Agent の常駐が必要です。
1. Datadog Agentのインストール
Datadogにログイン後、メニューから Infrastructure > Infrastructure List > Install the Datadog Agent に進み、お使いのOS(例: macOS)を選択します。表示されたインストールコマンドをターミナルで実行してください。
# macOS向けのインストールコマンド例(DD_SITEはご自身のアカウント環境に合わせて変更してください)
DD_API_KEY=<your_api_key> DD_SITE="ap1.datadoghq.com" bash -c "$(curl -L https://install.datadoghq.com/scripts/install_mac_os.sh)"
2. 認証キー(API Key / Application Key)の準備
TerraformからDatadogのAPIを操作するためには、2つのキーが必要です。
後ほど使用するため、取得したものをはメモしておいてください。
| キーの種類 | 主な用途・役割 | 取得方法 |
|---|---|---|
| API Key | ・AgentによるDatadogへのデータ送信 ・Terraformの基本認証 |
アカウント作成時に自動発行されたものをそのまま流用可能。 |
| Application Key | ・Terraformによるリソースの操作 (作成・変更・削除など) |
Datadogのコンソールから、あらかじめ手動で新規作成が必要。 |
事前準備2:監視対象アプリの作成とトレース送信(FastAPI + ddtrace)
TerraformでSLOを定義するには、実際にDatadogにトレースが流れている必要があります。今回は意図的に10%の確率でエラーを返すシンプルなFastAPIアプリを用意します。
app/main.py:
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import random
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/api/data")
def get_data():
# 10%の確率でエラーを返す(SLOの練習用)
if random.random() < 0.1:
return JSONResponse(status_code=500, content={"error": "something went wrong"})
return {"data": "hello world"}
ddtraceを使って起動する
以下のように ddtrace-run を使って実行することで、コードを書き換えることなく自動でDatadogにトレースが送信されます。
DD_SERVICE="sample-app" \
DD_ENV="dev" \
DD_VERSION="1.0" \
ddtrace-run python -m uvicorn main:app --reload
💡 ここで指定した
DD_SERVICEやDD_ENVの値が、そのままDatadog上での表示や検索タグになります。
別ターミナルでリクエストを叩いて動作確認します:
for i in {1..20}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/api/data; done
200と500が混在していれば正常です。DatadogのUI(APM → Traces → Live Search)でトレースが届いていることも確認できます。
Datadog Provider を設定する
準備したAPI KeyとApplication Keyを使って、TerraformからDatadogへ接続するための設定を行います。
terraform/provider.tf:
terraform {
required_providers {
datadog = {
source = "DataDog/datadog"
version = "~> 3.0"
}
}
}
provider "datadog" {
api_key = var.datadog_api_key
app_key = var.datadog_app_key
api_url = "https://ap1.datadoghq.com/"
}
キー情報はハードコードせず、変数化してセキュアに管理します。
terraform/variables.tf:
variable "datadog_api_key" {
type = string
sensitive = true
}
variable "datadog_app_key" {
type = string
sensitive = true
}
terraform.tfvars(※Git管理に含めないよう注意):
datadog_api_key = "xxxx_your_api_key_xxxx"
datadog_app_key = "xxxx_your_app_key_xxxx"
これらの設定が完了したら、初期化コマンドを実行してDatadogプロバイダをダウンロードします。
terraform init
Terraform has been successfully initialized!と表示されれば成功です 🎉
Datadog SLOを定義する
本題であるSLO(サービスレベル目標)を設定します。今回は、先ほど作ったFastAPIアプリの「API可用性(リクエスト成功率)99%」を目標とします。
slo.tf:
resource "datadog_service_level_objective" "api_availability" {
name = "API 可用性"
type = "metric"
description = "sample-appの/api/dataが99%以上成功すること"
query {
# 成功数 = 全リクエスト数 - エラー数
numerator = "sum:trace.fastapi.request.hits{service:sample-app,env:dev}.as_count() - sum:trace.fastapi.request.errors{service:sample-app,env:dev}.as_count()"
denominator = "sum:trace.fastapi.request.hits{service:sample-app,env:dev}.as_count()"
}
thresholds {
timeframe = "7d"
target = 99.0
warning = 99.5
}
tags = ["env:dev", "managed-by:terraform"]
}
ハマったポイント:!error タグは使えない
当初、分子(成功数)をシンプルに書こうとして、以下のような間違ったクエリを書いてしまいました。
# ❌ 動かない間違った書き方
numerator = "sum:trace.fastapi.request.hits{service:sample-app,!error}.as_count()"
APMが自動生成する trace.fastapi.request.hits には error タグが存在しません。
存在しないタグを否定(!error)しても何も除外されないため、常に100%と誤認されるバグが起きてしまいます。
正しくは、エラー専用の trace.fastapi.request.errors メトリクスを使い、全体(hits)から引くアプローチになります。
# ✅ 正しい書き方
numerator = "sum:trace.fastapi.request.hits{service:sample-app,env:dev}.as_count() - sum:trace.fastapi.request.errors{service:sample-app,env:dev}.as_count()"
コードを記述したら、再度 terraform apply で反映します。
Monitoring>SLOs にAPI 可用性という名前でSLOが追加されていれば成功です!
STATUSやERROR BUDGET等をグラフとして可視化することができました🎉

SLO Burn Rateアラートを作成する
SLOを定義しただけでは、リアルタイムに「どのくらいのペースでError Budgetを消費しているか」がわかりません。そこで、Error Budgetの消費速度を監視する Burn Rate(バーンレート)アラート を設定します。
📘 Burn Rate(消費速度)の基準値
-
Burn Rate = 1: 期間内(例:7日間)でちょうどError Budgetを綺麗に使い切るペース。
-
Burn Rate = 14.4: Burn Rate = 1 の 14.4倍の速度で予算を消費しているペース。GoogleのThe Site Reliability Workbookでは、この値に達した時点をPage(即時対応が必要な緊急アラート)を発火させる基準として推奨しています。
今回はBurn Rate = 14.4で設定しました。
terraform/slo_alert.tf:
resource "datadog_monitor" "slo_burn_rate" {
name = "SLO Burn Rate アラート"
type = "slo alert"
message = "Error Budgetの消費が速すぎます! @slack-datadog-alerts"
query = "burn_rate(\"${datadog_service_level_objective.api_availability.id}\").over(\"7d\").long_window(\"1h\").short_window(\"5m\") > 14.4"
monitor_thresholds {
critical = 14.4
}
tags = ["env:dev", "managed-by:terraform"]
}
💡補足:long_window(1h)と short_window(5m)の2つを使う理由(Multiwindow/Multi-Burn-Rate Alerts):
long_window(1h)と short_window(5m)の2つを組み合わせることで、「現在も進行中のエラー」だけに反応できるようになります。
-
5分(short_window)だけの場合:
一瞬のスパイク的なエラーに過剰反応してしまう(誤検知の可能性がある) -
1時間(long_window)だけの場合:
エラーが既に収束しているのにもかかわらず、過去のエラーの影響が計算に残り、アラートが長く鳴り続けてしまう -
両方の組み合わせ:
「現在もまだアクティブにエラーバジェットを消費し続けているか(現在もエラーが進行中か)」をチェックできるようになる
実行:
コードを記述したら、再度 terraform apply で反映します。
Monitoring>Custom Monitors にSLO Burn Rateという名前でアラートが追加されていれば成功です!
エラーを大量発生させてアラートが鳴るのを確認することができました🎉
for i in {1..500}; do curl -s http://localhost:8000/api/data; done
アラートをSlackへ通知する
障害発生時にチームがすぐ動けるよう、ここからは指定したSlackチャンネルへ通知を飛ばす設定を行っていきます。
DatadogとSlackの連携
- Slackで通知用チャンネル(例:
#datadog-alerts)を作成 -
https://ap1.datadoghq.com/integrations/slackにアクセスし、Slackワークスペースとの連携を認可します。 - Configurationタブ内の「Add Channel」にて、先ほど作成した
#datadog-alertsを登録します。
Terraform側の設定
slo_alert.tf の message に @slack-チャンネル名 を追記するだけです:
message = "Error Budgetの消費が速すぎます! @slack-datadog-alerts"
terraform apply 後、エラーを大量発生させて確認します:
for i in {1..500}; do curl -s http://localhost:8000/api/data; done
Slackに以下のような通知が届けば成功です🎉:
おわりに
今回はTerraformを活用し、Datadogでのインフラ監視からSLO定義、そして実践的なBurn Rateを用いたアラートの実装とSlack連携までを一気通貫で構築しました。
今までは「Datadogのダッシュボードを眺めるだけ」の側でしたが、自分でSLOのクエリを設計してコード化し、実用的なアラートを組むところまで予習できたことで、運用の仕組みへの理解がグッと深まりました。これで本番のタスクにも自信を持って臨めそうです!
📚 参考文献
- Google LLC. The Site Reliability Workbook - Chapter 5: Alerting on SLOs
(本記事の Burn Rate, Multiwindow/Multi-Burn-Rate Alerts の考え方の参考にしています)


