はじめに
この記事は「Medley (メドレー) Advent Calendar 2025」の21日目の記事です。
こんにちは、メドレーのSREチームに所属する@gongon282828です!
SREチームでは、サービスの監視の一部にDatadogを利用しています。
10月ごろにSRE強化の一環としてDatadogを色々いじくり回していて、Workflow Automationなるものを活用してみたので、その使い方について紹介します。
動機
そもそも、Datadogに限らず、監視アラートをトリガーにオートメーションを展開する場合、複数の処理ステップを介して、実装を行う必要があると思います。
特に、現在、生成AI真っ盛りです。
私の場合は、アラートをトリガーにして、発火したアラートをAIで解析したいと考え、何かしら良い方法はないかと考えていました。
同じようなニーズは増えているのではないでしょうか。
そういった中間処理のパイプラインとして、DatadogのWorkflow Automationを検証してみました。
Datadog Workflow Automationとは
簡単に言ってしまえば、AWSのStep Functionsのようなサービスです。
(以上!って感じでもある)
元々Datadogでは、多くのインテグレーションが存在しますが、それらを利用して柔軟性の高いアクションを実行することができ、テンプレート(Action Catalog)もたくさんあるみたいです。
(↑の他にも、GitHub、Slack、Anthropicへのアクションとか、他にも色々あった!)
個人的にメリットを感じたのが、Monitorの情報をトリガーにし、そのままDatadog完結でワークフローを実行できる点で、Datadogをメインの監視として活用している場合は便利に使えそうだと思いました。
例えば、以下のような煩雑なワークフローについて、それらがDatadogに集約できれば便利です!
- Datadog Export APIを利用してMonitorの情報をAPI Gateway + Lambdaで検知(PULL型 or PUSH型のどちらかで?)して、場合によってはさらにAWS外のサービスに展開してゴニョゴニョ...
実際にDatadogでワークフローを作ってみた!
要件は、以下のような形で、作ってみました!
- テストアプリにてAPM情報の収集とError Tracking設定の追加
- APMのError Trackingは、有効化しておく(理由は後述)
- DatadogとGitHubを連携する
- Error TrackingをトリガーにDatadog Workflow Automationを動かす
では、一つずつ、進めていきましょう!
テストアプリでAPM情報の収集とError Tracking設定の追加
まず、テストアプリでAPM周りとそのError Tracking設定の確認まで行います。
今回はAIで生成してもらった、Railsで動くテストアプリ(todo管理アプリ)に対して、APMの設定を導入しました。docker-compose.ymlに詳述してますが、Rails、nginx、MySQLで動かすアプリになっています。
以下のように、Datadog向けの設定を入れることで、APMとError Trackingの有効化設定が反映されます。
# config/initializers/datadog.rb
# トレーシング設定
c.tracing.enabled = true
c.tracing.report_hostname = true # ホスト名のレポート
c.tracing.log_injection = true # ログとトレースの関連付け
# Railsインストゥルメンテーション
c.tracing.instrument :rails, analytics_enabled: true
ここで注意が必要なのは、全てのAPMエラーを対象にワークフローを発火させた場合、ワークフローが大量発生してしまう点です。
そこで、APMのError Trackingを活用します。
Error Trackingでは、類似エラーを集約し、ひとまとまりとして拾えるようになるので、Error Tracking単位でワークフローを発火させることで、参照するエラーが重複したワークフローの発火を防ぐことができます。
以下、APM画面上でも確認できますが、ここでのError Trackingのエラーは、同じエラーが9つ発生しており、それらが一つのエラーとしてグルーピングされていることがわかります。
Datadog上のError専用の画面でも、エラーが集約されていることを確認できます。
ここまでで、APM設定とError Trackingの設定確認までができました。
DatadogとGitHubの連携
次に、DatadogとGitHubを連携します。
まず、DatadogのIntegrationsから、GitHubのアプリをインストールし、Datadogと連携させます。
GitHub側のGitHub Appの設定で、Datadogのインテグレーションを確認できればOKです。
まぁ、普段からやってそうな作業ですね!
Error TrackingをトリガーにDatadog Workflow Automationを動かす
ここからは、Error Trackingからワークフローを発火する流れを以下の順番で説明していきます。
- Datadog Workflow Automation自体の作成
- GitHubリポジトリでIssueを生成するDatadog Workflow Automationを作成
- Error Trackingをトリガーにする設定を追加
- Issue内のbodyにエラー詳細を出力する
Datadog Workflow Automation自体の作成
まずは、骨格となるワークフロー、GitHubリポジトリでIssueを生成するDatadog Workflow Automationを作成していきます。
メニューバーの[Automation]>>[Workflow Automation]に遷移し、New Workflowで、新しいワークフローを作成します。
AIでワークフローを作成できたりしますが、ここではTriggerをMonitorに設定します。
すると、以下のように、Monitorを出発点にしたMonitorだけのフローチャートが出現します。
また、Monitorのワークフロー名を、「@workflow-datadog-test」に変更します。
このワークフロー名は、追ってError Trackingを設定する際に、トリガー時の発火対象として必要になります。
さらに、ワークフローの「+」を押下すると、次のアクションを選択できるようになります。
今回は、GitHubリポジトリに対してIssueを作成させることが目的なので、「Create issue」のアクションを選択します。
Inputの中身は一旦、以下のように仮設定します。
Repository:
<your-org>/<your-repository>
Issue title:
APM Error Tracking test
Issue body:
test
その他、LabelやAssignees、期限等も設定できます。
Error Trackingをトリガーにする設定を追加
骨格となるワークフローができたので、発火元のError Trackingの設定を反映します。
メニューバーの[Monitors]の[New Monitor]で、新しいMonitorのError Trackingを作成します。
直近のエラーを見て、該当するエラーであれば、Trigger Workflowで先ほど作成したワークフローを指定して保存します。
ここまでで、一旦エラーが発生したのち、ワークフローからIssueを作成するところまでの設定は完了です。
ここから、動作検証を進めます。
今回作ったアプリでは、エラーを発生させた際に、ワークフローが発火したことを確認できるように仕込みを入れています。
# StandardError: これは意図的なテストエラーです (APM監視用)
curl -s http://localhost/error/test
# ActiveRecord::RecordNotFound: Couldn't find Todo with 'id'=999999999
curl -s http://localhost/error/database
上記のコマンドでエラーを発生させると、発火したワークフローをワークフロー一覧から確認できます。
下の画像では、Automatically via a Monitorと記載されているフローが、エラー発生時に自動で発火したワークフローになります。
また、各ワークフローの詳細を見ることで、input/outputやワークフロー失敗時のエラーを確認することができます。
ここまでで、ワークフロー自体の発火は確認できました。
Issue内のbodyにエラー詳細を出力させる
作成したIssueのbodyがtestだけだと、発火させても何を目的としたエラーかは判断できません。
そのため、Monitorの情報からIssueのbodyに記載したい情報を抽出し、テンプレートをMarkdown形式で作成していきます。
以下のサンプルのように、ワークフローのトリガーであるMonitorのアウトプットを加工・整形し、適切なIssue用のBodyを作成します。
MonitorのアウトプットJSON
{
"initiator": {
"email": "",
"id": "",
"name": "",
"orgId": ""
},
"monitor": {
"created": "YYYY-MM-DDTHH:MM:SS+00:00",
"created_at": 0,
"creator": {
"email": "***",
"handle": "***",
"id": "***",
"name": "***"
},
"deleted": null,
"draft_status": "published",
"evaluated_query": "sum:trace.rack.request.errors{...}by{env,service}.as_rate() / sum:trace.rack.request.hits{...}by{env,service}.as_rate()",
"event": {
"alert_type": "error",
"date_happened": 0,
"device_name": null,
"host": null,
"id": "***",
"payload": {
"alert_cycle_key": "***",
"assets": [],
"avalanche_window": null,
"group_transition_type": "no_grouping",
"message_parts": {
"last_triggered_ts": "YYYY-MM-DDTHH:MM:SSZ",
"links": [
{
"key": "status",
"text": "Monitor Status",
"url": "/monitors/***"
},
{
"key": "edit",
"text": "Edit Monitor",
"url": "/monitors/***/edit"
},
{
"key": "logs",
"text": "Related Logs",
"url": "/logs?query=..."
}
],
"message": "@workflow-name\n\nAlert message content.",
"message_prefix": "",
"message_suffix": "",
"query_plain": "min(last_15m):... > 0.1",
"query_summary": "min(last_15m):... > 0.1"
},
"monitor": {
"created_at": 0,
"deleted": null,
"draft_status": "published",
"id": "***",
"message": "@workflow-name\n\nAlert message content.",
"modified": 0,
"name": "[SAMPLE] High Error Rate on {{service.name}}",
"options": {
"escalation_message": "",
"include_tags": true,
"new_group_delay": 0,
"notify_audit": false,
"on_missing_data": "default",
"renotify_interval": 0,
"require_full_window": false,
"silenced": {},
"thresholds": {
"critical": 0.1
}
},
"org_id": "***",
"query": "min(last_15m):... > 0.1",
"tags": ["monitor_pack:apm"],
"templated_name": "[SAMPLE] High Error Rate on ",
"type": "query alert"
},
"reduced_message_text": "@workflow-name\n\nAlert message content.\n\nMetric value: 0.0",
"result": {
"avalanche": false,
"display_logs_sample": {},
"evaluation_ts": 0,
"group": null,
"group_key": null,
"groups": {
"*": {
"status": 1
}
},
"logs_url": "/logs?query=...",
"metadata": {
"alert_url": "/monitors/***",
"is_usertest": false,
"metric": "trace.rack.request.errors,trace.rack.request.hits",
"monitor_id": "***",
"priority_list": {
"message": null,
"original_priority": null,
"recovery_message": null
},
"snap_url": "***"
},
"num_groups": 1,
"result_id": 0,
"result_ts": 0,
"scheduled_ts": 0,
"state_counts": {
"0": 0,
"1": 1,
"2": 0,
"3": 0,
"5": 0,
"6": 0
},
"state_id": 1
},
"states": {
"dest_state": "Alert",
"source_state": "OK"
},
"sub_group_count": null,
"sub_groups_sample": null,
"text_only_message": "@workflow-name\n\nAlert message content.\n\nMetric value: 0.0",
"transition": {
"trans_name": "Triggered",
"trans_type": "alert"
}
},
"priority": "normal",
"tag_value": {
"monitor": "monitor",
"monitor_pack": "apm",
"source": "alert"
},
"tag_value_list": {
"monitor": ["monitor"],
"monitor_pack": ["apm"],
"source": ["alert"]
},
"tags": ["monitor", "monitor_pack:apm", "source:alert"],
"text": "@workflow-name\n\nAlert message content.",
"title": "[Triggered] [SAMPLE] High Error Rate on ",
"url": "https://app.datadoghq.com/event/event?id=***"
},
"group_value": {
"*": "*"
},
"group_value_list": {
"*": ["*"]
},
"id": "***",
"message": "@workflow-name\n\nAlert message content.",
"modified": "YYYY-MM-DDTHH:MM:SS+00:00",
"multi": true,
"name": "[SAMPLE] High Error Rate on ",
"options": {
"escalation_message": "",
"include_tags": true,
"new_group_delay": 0,
"notify_audit": false,
"on_missing_data": "default",
"renotify_interval": 0,
"require_full_window": false,
"silenced": {},
"thresholds": {
"critical": 0.1
}
},
"org_id": "***",
"overall_state": "Alert",
"overall_state_modified": "YYYY-MM-DDTHH:MM:SS+00:00",
"priority": null,
"query": "min(last_15m):... > 0.1",
"restricted_roles": null,
"state": {
"groups": {
"env:ENV_NAME,service:SERVICE_NAME": {
"last_nodata_ts": null,
"last_notified_ts": 0,
"last_resolved_ts": 0,
"last_triggered_ts": 0,
"name": "env:ENV_NAME,service:SERVICE_NAME",
"status": "Alert"
}
}
},
"tag_value": {
"monitor_pack": "apm"
},
"tag_value_list": {
"monitor_pack": ["apm"]
},
"tags": ["monitor_pack:apm"],
"type": "query alert",
"url": "https://app.datadoghq.com/monitors/***"
},
"name": "[Triggered] [SAMPLE] High Error Rate on ",
"runAsUser": {
"email": "***",
"id": "***",
"name": "***",
"orgId": "***"
},
"type": "monitor",
"url": "https://app.datadoghq.com/monitors/***"
}
実際のIssueのbodyは、上記のJSONから値を抽出し、以下のようなMarkdown形式で登録しました。
JSONから抽出したMarkdown形式テンプレート
## APM Error Alert - Auto Analysis
### Monitor Information
- **Monitor Name:** {{ Source.monitor.name }}
- **Monitor ID:** {{ Source.monitor.id }}
- **Status:** {{ Source.monitor.overall_state }}
- **Type:** {{ Source.monitor.type }}
---
### Alert Details
**Query:**
{{ Source.monitor.query }}
**Threshold:** {{ Source.monitor.options.thresholds.critical }}
---
### Alert Message
{{ Source.monitor.message }}
---
### State Transition
- **From:** {{ Source.monitor.event.payload.states.source_state }}
- **To:** {{ Source.monitor.event.payload.states.dest_state }}
- **Transition:** {{ Source.monitor.event.payload.transition.trans_name }}
- **Triggered At:** {{ Source.monitor.event.payload.message_parts.last_triggered_ts }}
---
### Quick Links
- [Monitor Status]({{ Source.monitor.url }})
- [Edit Monitor](https://app.datadoghq.com/monitors/{{ Source.monitor.id }}/edit)
---
<details>
<summary>Event Details (Click to expand)</summary>
- **Event ID:** {{ Source.monitor.event.id }}
- **Alert Type:** {{ Source.monitor.event.alert_type }}
- **Priority:** {{ Source.monitor.event.priority }}
- **Tags:** {{ Source.monitor.tags }}
</details>
---
### Next Steps
- [ ] エラーの原因を調査
- [ ] 影響範囲を確認
- [ ] 修正対応
- [ ] 再発防止策の検討
---
_This issue was automatically created by Datadog Workflow Automation_
Error Trackingからワークフローを発火させ、実際に出力されたIssueはこちらになります。
以上、ここまでで、目指していたワークフローは完成です!
補足
ちなみに、今回はコンソール上でワークフローの構築を進めましたが、ワークフロー全体をJSONとして出力させることもできます。
そのため、一度コンソール上で作り込んでしまえば、IaC等でも活用できると思います。
作成したWorkflow AutomationのアウトプットJSON
{
"id": "xxxxxxxxxxxxxxxxxx",
"name": "datadog-test",
"description": "",
"tags": [],
"published": true,
"spec": {
"triggers": [
{
"startStepNames": [
"Create_issue"
],
"monitorTrigger": {}
}
],
"steps": [
{
"name": "Create_issue",
"actionId": "com.datadoghq.github.createIssue",
"parameters": [
{
"name": "repository",
"value": "md-shingo-kawamoto/datadog-test"
},
{
"name": "title",
"value": "APM Error Tracking test"
},
{
"name": "body",
"value": "## APM Error Alert - Auto Analysis\n\n### Monitor Information\n- **Monitor Name:** {{ Source.monitor.name }}\n- **Monitor ID:** {{ Source.monitor.id }}\n- **Status:** {{ Source.monitor.overall_state }}\n- **Type:** {{ Source.monitor.type }}\n\n---\n\n### Alert Details\n\n**Query:**\n```\n{{ Source.monitor.query }}\n```\n\n**Threshold:** {{ Source.monitor.options.thresholds.critical }}\n\n---\n\n### Alert Message\n\n{{ Source.monitor.message }}\n\n---\n\n### State Transition\n- **From:** {{ Source.monitor.event.payload.states.source_state }}\n- **To:** {{ Source.monitor.event.payload.states.dest_state }}\n- **Transition:** {{ Source.monitor.event.payload.transition.trans_name }}\n- **Triggered At:** {{ Source.monitor.event.payload.message_parts.last_triggered_ts }}\n\n---\n\n### Quick Links\n- [Monitor Status]({{ Source.monitor.url }})\n- [Edit Monitor](https://app.datadoghq.com/monitors/{{ Source.monitor.id }}/edit)\n\n---\n\n<details>\n<summary>Event Details (Click to expand)</summary>\n\n- **Event ID:** {{ Source.monitor.event.id }}\n- **Alert Type:** {{ Source.monitor.event.alert_type }}\n- **Priority:** {{ Source.monitor.event.priority }}\n- **Tags:** {{ Source.monitor.tags }}\n\n</details>\n\n---\n\n### Next Steps\n\n- [ ] エラーの原因を調査\n- [ ] 影響範囲を確認\n- [ ] 修正対応\n- [ ] 再発防止策の検討\n\n---\n\n_This issue was automatically created by Datadog Workflow Automation_"
}
],
"display": {
"bounds": {
"x": 0,
"y": 192
}
}
}
],
"handle": "datadog-test"
}
}
以上、こんな感じで、APMのエラートラッキングからGitHubへの処理まで、Datadogで完結してワークフローを作ることができました。
番外編:Error Tracking上で問題ソースを参照できるようにする
ついでに番外編として、DatadogのError Tracking側で、GitHubのソースコードを参照させ、問題を特定しやすいようにする方法を紹介します。
アプリのソースコードとGitHubのAPM連携を行うことで、簡単に設定できるので、便利です。
ソースコードの修正内容と、DatadogとGitHubの設定変更の順番で解説します。
ソースコードの修正内容
GitHubのソースコードとAPMを連携するには、Rails側では以下の設定変更が必要です。
# config/initializers/datadog.rb
# リポジトリURLを設定
c.tags['git.repository_url'] = ENV.fetch('DD_GIT_REPOSITORY_URL', 'https://github.com/md-shingo-kawamoto/datadog-test')
c.tags['git.commit.sha'] = ENV.fetch('DD_GIT_COMMIT_SHA', nil) if ENV['DD_GIT_COMMIT_SHA']
上記の環境変数も追加する必要があります。
ここでは、docker-compose.ymlで記載することにします。
environment:
# GitHub ソースコード連携
- DD_GIT_REPOSITORY_URL=${DD_GIT_REPOSITORY_URL:-https://github.com/md-shingo-kawamoto/datadog-test}
- DD_GIT_COMMIT_SHA=${DD_GIT_COMMIT_SHA:-}
DatadogとGitHubの設定変更
APMのソースコードリンク設定画面で、GitHubリポジトリとAPMを紐付けます。
これだけでAPMがソースコードを追従してくれます。
設定が完了したので、再度、エラー発生テストコードを実行します。
# StandardError: これは意図的なテストエラーです (APM監視用)
curl -s http://localhost/error/test
# ActiveRecord::RecordNotFound: Couldn't find Todo with 'id'=999999999
curl -s http://localhost/error/database
以下のように、Error Tracking上で、ソースコードの問題点も含めてDatadogと連携されていることが確認できます。
- StandardError
- ActiveRecord::RecordNotFound
ちなみに、GitHub連携前に発生させたエラーのdatabase existsでは、ソースコードは確認できない画面のままです。
Datadogコンソール上からエラー発生要因のソースコードまでチェックできるので、とても便利そうです!
まとめ
Datadog Workflow Automationで、APMエラーからGitHub Issueを自動生成してみました。
他にも、GitHub側のイベントを検知してワークフローを動かす仕組みがあったり、GitHub Actionsを動かしたりできます。実際に、GitHub ActionsのワークフローからClaudeを発火させ、APMエラーに対するソースコード修正PR生成も可能でした。
もちろん万能ではなく、思いがけない制限もあるので、そこがハマりポイントになることもありそうです。(Datadog側の問題/外部インテグレーション先の問題かは置いといて...)
本格的なCI/CDとまではいきませんが、MonitorをトリガーにDatadog Workflow Automationを発火させることで、色々捗るSRE活動もありそうです。
何にしてもそうですが、上手に活用できればと思いました!
We’re hiring!
メドレーでは様々な職種で、スペシャリストを募集しています!
22日目の担当は@izooさんの「チーム内部からQA組織を立ち上げて半年 ──品質文化醸成に向けて」についてです!!
お楽しみに!!



















