BeeXの井尻です。先日、膨張してしまっていた3DSのバッテリーを交換したことをきっかけに3DS熱が再燃しています。外出の際は常にカバンに3DSが入っている生活を送っているのですが、地方在住なこともあり、今のところすれ違い通信は出来ていません。
今度東京に行くときが楽しみです。
はじめに
みなさま、DatadogのAutomation Workflowを使ったことはあるでしょうか。
モニターアラートへの自動応答からSlack通知、OpenAI APIを始めとする外部APIとの連携まで、幅広いことができて非常に便利な機能です。
一方で、2026/07時点でDatadogのアクションだけでも516もあり、できることが多い分、「シンプルなことをやりたいだけなのにどこから手をつければいいか分からない」と感じることも多いのではないでしょうか。
そこで、この記事では「週次でメトリクスを集計し、Slackに投稿する」というワークフローを実際に作りながら、以下の内容を実際の画面付きで解説したいと思います。
- トリガーの設定
- メトリクス・ログ・スパンの取得方法
- JavaScriptステップでのデータ整形
- Slackへの送信
- 時刻の扱い方
- つまづきやすいポイント
1. Datadog Automation Workflowとは

たとえば以下のようなことが可能です。
- モニターがアラート状態になったとき、自動でPagerDutyにインシデントを作成する
- 毎週決まった時間にDatadogのメトリクスを集計してSlackに投稿する
- GitHub Actionsと連携してデプロイ完了後に通知を送る
各処理は「ステップ」という単位で定義し、GUIから組み合わせてワークフローを構築します。ステップ間でデータを受け渡すことができるため、前のステップの結果を使って次の処理を行う、といったことも簡単にできます。
詳細は公式ドキュメントを参照ください。
2. 実践
ここでは「週次でメトリクスを集計し、Slackに投稿する」ワークフローを作りながら解説していきます。全体の流れは以下のとおりです。
[Scheduleトリガー] ↓ [メトリクス取得] [ログ取得] [スパン取得] ↓ [JavaScriptで整形] ↓ [Slackに送信]
なお、ワークフローはPublishしなければ課金対象になりません。試行錯誤しながら作る際は、Publishせずにテスト実行を繰り返すのが安心です。
以下は本記事で作成するサンプルワークフローの完成図です。

2.1. トリガーを設定する
ワークフローを作成するには、まずトリガーの選択が必要です。モニターのアラート発火やWebhook受信など複数の種類がありますが、今回は扱いやすい 「Schedule」 を選択します。

※トリガーを選択せずとも、生成AIに作成したいワークフローについての仕様を伝えると、ある程度自動で作成することも可能です。
Schedule Triggerの実行タイミングは Repeat everyやTimezoneなどを選択して決定します。

なお、このトリガーの起動時刻はそのままメトリクスの集計期間として使えるわけではありません。「先週1週間分」のような期間を計算するには別途JSステップなどが必要です(→2.6.)。
2.2. メトリクスを取得する
メトリクスにまつわるアクションはメトリクス | Datadog API Referenceに一覧があります。

| アクション名 | 概要 |
|---|---|
| Get timeseries points | 指定した期間のメトリクスを時系列データ(タイムスタンプ付きの複数値)として取得する |
| Query timeseries data | v2版の時系列クエリ。メトリクス以外にログやAPMも対象にできる |
| Query scalar data | 指定した期間のメトリクスをスカラー値(1つの集計値)として取得する |
それぞれ用途によって使い分ける必要がありますが、ここでは 「Query scalar data」 を使いたいと思います。

次の通り、クエリは複数設定可能で、1ステップで複数のメトリクスを一括取得することができます。 クエリや集計期間の指定はGUIから設定することもできますが、JSONで直接定義することも可能です。
queryにあたる部分は自身のDatadogにデータ連携しているデータから、適当なものに置き換えてください。
{ "queries": [ { "aggregator": "avg", "data_source": "metrics", "name": "q0", "query": "sum:aws.lambda.invocations{functionname:my-function}.as_count()" }, { "aggregator": "avg", "data_source": "metrics", "name": "q1", "query": "avg:aws.lambda.duration.p99{functionname:my-function} by {service}" } ], "formulas": [ { "formula": "q0" }, { "formula": "q1" } ], "range": "1h" }
なお、今回はログとスパンの取得にそれぞれ専用のアクションを使います(後述)。Log Explorer・Trace Explorerと同じクエリ構文がそのまま使えるためです。
2.3. ログを取得する
ログにまつわるアクションはLogs | Datadog API Referenceに一覧があります。

「Logs」という名前がついたカテゴリだけでも、Logs / Logs Archives / Logs Custom Destinations / Logs Indexes / Logs Metrics / Logs Pipelines など複数の種類があります。ここではログイベントそのものを扱う 「Logs」 カテゴリに絞ります。
Workflowのコンソール上は以下の3つのアクションとして表示されます。なお、APIドキュメント上ではSearch LogsがGET・POSTに分かれていますが、Workflowステップとしては1つに統合されています。
| アクション名 | 概要 |
|---|---|
| Aggregate events | ログイベントを集計し、カウントなどのスカラー値として取得する |
| Search Logs | 指定したクエリに一致するログイベントの一覧を取得する |
| Send logs | Datadogにログを送信する(書き込み専用) |

queryにあたる部分は自身のDatadogにデータ連携しているデータから、適当なものに置き換えてください。
{ "filter": { "from": "now-1h", "query": "service:my-service @error.type:timeout", "to": "now" }, "compute": [ { "aggregation": "count", "metric": "c0" } ] }
結果は以下のような構造で返ってきます。
{ "buckets": [ { "by": {}, "computes": { "c0": 42 } } ] }
JavaScriptステップから参照する場合は次のようになります。
var count = $.Steps.Aggregate_events.data.buckets[0].computes.c0;
2.4. スパン(APMトレース)を取得する
スパンにまつわるAPIカテゴリには、名前が似た以下の2種類があります。

| カテゴリ | 概要 |
|---|---|
| Spans | Datadog API Reference | Datadogに蓄積されたスパンデータをクエリ・集計する |
| Spans Metrics | Datadog API Reference | スパンから継続的にメトリクスを生成するルールを管理する(設定のCRUD) |
Spans Metricsはあくまでメトリクス生成ルールの設定であり、スパンデータそのものを取得するわけではありません。スパンの内容を参照したい場合は 「Spans」 を使います。
Spansカテゴリのアクションは以下の3つです。
| アクション名 | 概要 |
|---|---|
| Aggregate spans | スパンを集計し、カウントなどのスカラー値として取得する |
| Search spans (POST) | 指定したクエリに一致するスパンの一覧を取得する |
| List spans (GET) | 指定したクエリに一致するスパンの一覧を取得する |

queryにあたる部分は自身のDatadogにデータ連携しているデータから、適当なものに置き換えてください。
{ "query": "service:my-service", "compute": [ { "aggregation": "count", "metric": "c0" } ], "timezone": "Asia/Tokyo", "timeframe": "1h" }
結果の構造はログとは異なり、データが配列で返ってきます。
[ { "attributes": { "compute": { "c0": 15 } } } ]
なお、ヒットするスパンが0件の場合は空配列 [] が返るため、JavaScriptで参照する際は長さを確認する必要があります。
function getTraceCount(step) { var d = step.data; if (Array.isArray(d)) { return d.length ? d[0].attributes.compute.c0 : 0; } return null; }
2.5. JavaScriptで整形する
データの加工・変換を行いたいときは、「Data Transformation」 カテゴリのステップを使います。

Expression / JavaScript / Python / JavaScript (Script) / Convert XML to JSON といった種類がありますが、ここでは JavaScript を使います。
2.5.1. 基本的な書き方
他のステップの結果を参照するには、$.Steps.ステップ名 という形式を使います。
var cols = $.Steps.Query_scalar_data.data.attributes.columns;
Query scalar dataの結果カラムはインデックスではなく名前(q0, q1, q2...)で取得する必要があります。カラムの返却順序が保証されていないためです。WorkflowのGUIでクエリを設定した場合、クエリ名はデータソースを問わず a, b, c, d のようにアルファベット順に付与されます(JSONで直接定義した場合は name フィールドで自由に指定できます)。
function getVal(cols, name) { if (!cols) return null; for (var i = 0; i < cols.length; i++) { if (cols[i].name === name) { var col = cols[i]; if (col.type === 'number' && col.values) { for (var j = 0; j < col.values.length; j++) { if (col.values[j] != null) return col.values[j]; } } return null; } } return null; } var cols = $.Steps.Query_scalar_data.data.attributes.columns; var invocations = getVal(cols, 'q0'); var duration_p99 = getVal(cols, 'q1');
JSステップは必ずオブジェクトを return する必要があります。Slackなどのテンプレート式から参照する場合は .data.キー名 でアクセスできます。
return { message: "Slackに送るテキスト", alertCount: 3 }; // Slackテンプレートからは {{ Steps.JavaScript.data.message }} で参照
2.5.2. サンプルコード
以上の基本的な書き方を踏まえたサンプルコードです。
var $S = $.Steps; // メトリクス: カラム名で引く(返却順序が保証されないためインデックス不可) function getVal(cols, name) { if (!cols) return null; for (var i = 0; i < cols.length; i++) { if (cols[i].name === name) { var col = cols[i]; if (col.type === 'number' && col.values) { for (var j = 0; j < col.values.length; j++) { if (col.values[j] != null) return col.values[j]; } } return null; } } return null; } // ログ: buckets[0].computes.c0 function getLogCount(step) { try { var b = step.data.buckets; return b && b.length ? b[0].computes.c0 : 0; } catch(e) { return null; } } // スパン: 配列で返るため length チェックが必要 function getSpanCount(step) { try { var d = step.data; return Array.isArray(d) ? (d.length ? d[0].attributes.compute.c0 : 0) : null; } catch(e) { return null; } } var cols = $S.Query_scalar_data.data.attributes.columns; var invocations = getVal(cols, 'q0'); var duration = getVal(cols, 'q1'); var errorCount = getLogCount($S.Aggregate_events); var spanCount = getSpanCount($S.Aggregate_spans); // 後続ステップからは $.Steps.このステップ名.result.message で参照 return { message: '実行数: ' + invocations + ' / エラー数: ' + errorCount + ' / スパン: ' + spanCount, };
2.5.3. 注意点
$.Steps プレフィックスを省略しない
Steps.ステップ名 と書くと Steps is not defined エラーになります。必ず $.Steps.ステップ名 と書きましょう。
// NG var cols = Steps.Query_scalar_data.data.attributes.columns; // OK var cols = $.Steps.Query_scalar_data.data.attributes.columns;
スクリプトは10,240バイト制限がある
JavaScriptステップには 10,240バイト の制限があります。恐らく日本語はUTF-8換算で1文字3バイトになっているため、文字数以上に消費します。制限に引っかかった場合は不要なコメントを削除するか、変数名を短縮するなどで対応しましょう。
2.6. (おまけ)時刻を渡す
スケジュールトリガーで起動する場合、集計対象の期間(from/to)をJSステップで計算して後続ステップに渡すと便利です。
JavaScriptステップで Date オブジェクトを使って期間を計算できます。JST(UTC+9)で「毎週金曜10時〜翌週金曜10時」を計算する例です。
var now = new Date(); // 直近の金曜日 10:00 JST を求める(UTC 01:00 = JST 10:00) var day = now.getUTCDay(); // 0=日, 5=金 var daysToFriday = (day >= 5) ? (day - 5) : (day + 2); var currentEnd = new Date(now); currentEnd.setUTCDate(now.getUTCDate() - daysToFriday); currentEnd.setUTCHours(1, 0, 0, 0); // JST 10:00 var currentStart = new Date(currentEnd); currentStart.setUTCDate(currentEnd.getUTCDate() - 7); var previousStart = new Date(currentStart); previousStart.setUTCDate(currentStart.getUTCDate() - 7); return { currentStart: currentStart.toISOString(), currentEnd: currentEnd.toISOString(), previousStart: previousStart.toISOString(), previousEnd: currentStart.toISOString(), };
表示用の文字列を作るときは、toISOString() がUTC時刻を返すことに注意が必要です。JSTで表示したい場合はオフセット(9時間)を加算してから文字列に変換しましょう。
function toJSTString(d) { var jst = new Date(d.getTime() + 9 * 60 * 60 * 1000); return jst.toISOString().replace('T', ' ').slice(0, 16) + ' JST'; }
2.7. Slackにメッセージを送る
Slackに対して何かを実行する場合には、 「Slack」 カテゴリのアクションを使います。

メッセージを送るアクションには、次の2つがありますが、ここではシンプルな 「Send Message」 を使います。
| アクション名 | 概要 |
|---|---|
| Send Message | テキストメッセージをチャンネルに送信する |
| Send Block Kit message | Block Kitを使ったリッチなレイアウトのメッセージを送信する |

設定項目は通知先とメッセージ本文のみです。WorkSpacesを選び、チャンネルまたは個人ユーザー(DMに届きます)を選択し、メッセージ本文にはJSステップの出力をテンプレート式で参照します。
{{ Steps.JavaScript.data.message }}
2.8. その他つまずきやすいポイント
2.8.1. テスト実行時のステップ参照
テスト実行時に特定のステップをスキップすると、後続のJSステップでそのステップを参照した際にエラーになることがあります。全ステップをつなげた状態でテスト実行するか、try/catch で参照をガードしておくと安全です。
function getCols(step) { try { return step.data.attributes.columns; } catch(e) {} try { return step.result.data.attributes.columns; } catch(e) {} return null; }
2.8.2. デバッグ用の return を消し忘れない
開発中に途中経過を確認するため return { debug: ... } を書いてしまいがちですが、本番に持っていく前に必ず削除しましょう。後続のSlackステップがメッセージ文字列を期待しているのに別の構造が返ってくると、バリデーションエラーになります。
2.8.3. Publishしなくても動作確認できる
ワークフローはPublishしない状態でも「Run」ボタンからテスト実行できます。Publishしなければ課金されません。 ステップを一つ変えるたびにテストを回しながら少しずつ構築していくのがおすすめです。
2.9. サンプル実行する
2.9.1. ここまでに作成したステップを連携する
作成したステップをホバーすると、+アイコンが表示されます。+アイコンから、繋げたいステップまでをドラッグして連携させます。

なお、矢印アイコンから繋げるステップは、そのステップでエラーが発生したときに進む経路となります。

2.9.2. テスト実行する
画面右上のRunボタンを押下すると、作成したワークフローをテストすることができます。スケジュールなどのトリガーを設定していても、自動でManualに置き換わり、即時実行されます。

Run WorkflowモーダルでRunボタンを押下すると、実際に各ステップが実行されていきます。
無事にSlackにメッセージが届けば、Workflowは問題なく完了しています!

2.10. 作成したワークフローの片づけ
今回検証で作成したワークフローの削除手順です。右上の歯車マークをクリックし、「Delete workflow」を押下、確認モーダルでOKを押せば、作成したワークフローを削除することができます。 Unpublish状態でも他の人には作成したワークフローが見えるため、不要なワークフローはしっかり削除しておきましょう。

3. まとめ
いかがだったでしょうか。Datadog Automation Workflowは、GUI・JSON・JavaScriptなどを組み合わせ、柔軟にワークフローを構築できる強力なツールです。 ご紹介できていない、たくさんのアクションやDatastoreといった機能を組み合わせれば、もっと高機能なワークフローを構築することもできます。
今回解説した内容を振り返ります。
- ログ・スパン取得には「Aggregate events」「Aggregate spans」を。Log/Trace Explorerと同じクエリ構文がそのまま使える
- カラムはインデックスでなく名前で取得する。返却順が保証されていないため
- 他ステップの参照は必ず
$.Steps.ステップ名の形式で - JSのreturn値はSlackなどのテンプレート式から
.data.キー名で参照できる - スクリプトは10,240バイト制限あり。日本語コメントは早めに削る
他にもCloudWatchやPagerDutyとの連携、モニターの自動対応など、Datadogのあらゆるデータを活用した自動化が可能です。ぜひ試してみてください。