📌 はじめに
実装の背景と目的
とあるアプリケーションがサーバー上で稼働していましたが、これまでアラートの設定が行われていませんでした。今回、エラーをリアルタイムに検知し、チームが即座に対応できる体制を構築するため、AWS CloudWatch Logs と Slack を連携した通知システムを Terraform で実装しました。
設定パラメータの意味や、ハマりどころをまとめました。
AWS Chatbot を使うメリット
📝 注記: AWS Chatbot は 2025 年 2 月 19 日に Amazon Q Developer に変更されました。マネージメントコンソール上は、Amazon Q Developer in chat applications となっています。本記事では従来の名称「AWS Chatbot」を使用しますが、機能は同じです。字面の関係上、名称が長いので Chatbot でいかせてもらいます。
従来は Lambda を使った通知が一般的でしたが、AWS Chatbot を使うことで以下のメリットがあります:
| 項目 | Lambda パターン | AWS Chatbot パターン |
|---|---|---|
| コード管理 | Lambda 関数のコード管理・デプロイが必要 | 不要 – 設定のみで完結 |
| メンテナンス | ランタイムバージョン管理、依存関係更新 | AWS が管理 – 自動更新 |
| 実装難易度 | Slack API の実装、エラーハンドリング | 簡単 – 宣言的設定のみ |
| コスト | Lambda 実行料金 | 無料 – Chatbot 自体は無料 |
| 信頼性 | 自前実装の品質に依存 | AWS が保証 – マネージドサービス |
| インタラクティブ対応 | カスタム実装が必要 | 組み込み – ボタン操作対応 |
結論: 通知目的だけなら、AWS Chatbot の方が圧倒的に効率的です。
アーキテクチャ構成の理解
AWS Chatbot を使った通知の仕組みは、AWS のサービス連携により CloudWatch Logs → Metric Filter → Alarm → SNS → Chatbot → Slack という流れになります。特に、Chatbot は SNS 経由でしか動作しないという AWS の制約があるため、必然的にこの構成となります。
なぜ SNS 経由なのか?
Amazon Q Developer in chat applications (旧 AWS Chatbot) は、SNS Topic 経由でのみ通知を受け取るという仕組みになっています。
AWS の制約:
- ❌ CloudWatch Alarm → Slack への直接通知は不可能
- ✅ CloudWatch Alarm → SNS → Amazon Q Developer → Slack という経路が必須
この制約は AWS のアーキテクチャ設計によるもので、すべての AWS サービスが SNS を中心としたイベント駆動型の統合を採用しているためです。
参考: 公式ドキュメント – Monitoring AWS services
“All services that work with Amazon Q Developer in chat applications use Amazon SNS topics as targets to send event and alarm notifications.”
📋 前提条件
本記事で紹介する実装は、以下の環境を前提としています。
必須環境・ツール
| 項目 | バージョン | 備考 |
|---|---|---|
| Terraform | >= 0.14.0 | 本実装では 1.x 系を推奨 |
| AWS Provider | ~> 5.61.0 | AWS Chatbot リソース対応バージョン |
| AWS アカウント | – | CloudWatch、SNS、Chatbot の操作権限が必要 |
| Slack ワークスペース | – | チャンネル作成・管理権限が必要 |
環境
1. CloudWatch Logs へのログ出力
アプリケーションから CloudWatch Logs にログが出力されている状態です。
本実装では以下の構成を前提としています:
- ログ出力元: ECS Fargate (API/Batch コンテナ)
-
Log Group 名:
/ecs/api,/ecs/batch -
ログドライバー:
awslogs(ECS Task Definition で設定)
2. ログフォーマット: JSON 形式
エラー検知のため、ログは JSON 形式 で level_name フィールドを含む必要があります。
本リポジトリの実際のログ例:
{
"level_name": "ERROR",
"message": "request_error",
"context": {
"status": 500,
"exception": {
"class": "RuntimeException",
"message": "Database connection failed",
"trace": "..."
}
},
"datetime": "2025-10-21T03:07:31.263879+00:00"
}
CloudWatch Log Metric Filter のパターン:
{ $.level_name = "ERROR" }
JSON ログから level_name が "ERROR" のログを抽出します。
必要な権限
AWS 側の権限
本実装を実行するユーザー/ロールには、以下のサービスの権限が必要です:
- CloudWatch Logs: Log Group の読み取り、Log Metric Filter の作成
- CloudWatch Alarms: Alarm の作成・管理
- SNS: Topic の作成、ポリシーの設定
- AWS Chatbot: Chatbot Configuration の作成、IAM Role の管理
- IAM: Chatbot 用 Role の作成
Slack 側の権限
- ワークスペース管理者権限: OAuth 認証のため
- チャンネル作成権限: 通知先チャンネルの準備
🏗️ システムアーキテクチャとデータフロー
アーキテクチャ全体像
通知システムは以下のコンポーネントで構成され、CloudWatch Logs → Metric Filter → Alarm → SNS → Chatbot → Slack という流れでエラーを検知・通知します。

各コンポーネントの役割
| コンポーネント | 責務 | 主な機能 | 設定のポイント |
|---|---|---|---|
| CloudWatch Logs | ログ収集 | アプリケーションからの JSON ログを受信・保存 | Log Group 名、保持期間の設定 |
| Log Metric Filter | ログ解析 | JSON パターンマッチングでエラーログを抽出 |
{ $.level_name = "ERROR" } パターン |
| CloudWatch Metric | メトリクス集計 | エラー数を時系列データとして集計 | Namespace、メトリクス名の設計 |
| CloudWatch Alarm | 閾値監視 | メトリクスが閾値を超えたらアラートを発火 | 閾値、評価期間、統計方法の選択 |
| SNS Topic | メッセージング | アラーム通知を受信し、サブスクライバーに配信 | アクセス権限ポリシーの設定 |
| AWS Chatbot | 通知変換 | SNS メッセージを Slack フォーマットに変換 | Slack 認証、IAM Role の設定 |
| Slack Channel | 可視化 | チームメンバーにリアルタイムで通知 | チャネル ID、ワークスペース ID の取得 |
エラー発生から通知までの流れ
エラー発生から Slack 通知までの詳細なシーケンス:
-
エラー発生 (Application Layer)
- API/Batch で例外が発生し、JSON 形式でログ出力
- 例:
{"level_name": "ERROR", "message": "request_error", "context": {...}}
-
ログ収集 (CloudWatch Logs) – 1 秒以内
- ECS Fargate から CloudWatch Logs
/ecs/apiまたは/ecs/batchにログが送信される
- ECS Fargate から CloudWatch Logs
-
パターンマッチング (Log Metric Filter) – リアルタイム
-
{ $.level_name = "ERROR" }でエラーログを抽出 - マッチしたログ 1 件につき、メトリクス値を
1増加
-
-
メトリクス集計 (CloudWatch Metric) – 60 秒間
- 60 秒間のエラーログ件数を合計 (
Sum) -
APIErrorCountまたはBatchErrorCountメトリクスとして記録
- 60 秒間のエラーログ件数を合計 (
-
閾値評価 (CloudWatch Alarm) – 60 秒ごと
-
Sum >= 3(デフォルト閾値) かチェック - 閾値を超えた場合、
ALARM状態に遷移
-
-
通知発行 (SNS Topic)
- CloudWatch Alarm から SNS Topic にメッセージ発行
- サブスクライバー(Chatbot)にメッセージ配信
-
Slack 形式変換 (AWS Chatbot)
- SNS メッセージを Slack フォーマットに変換
- アラーム詳細やインタラクティブボタンを追加
-
通知表示 (Slack) – 合計 1-2 分
-
#alertsチャネルにメッセージを投稿 - 担当者に即時通知
-
復旧フロー: エラー数が閾値を下回ると、OK 状態に遷移し、復旧通知が送信されます(ok_actions が設定されている場合)
🛠️ Terraform 実装の詳細解説
データの流れに沿って、各コンポーネントの Terraform 実装例を解説します。
a) Log Metric Filter (aws_cloudwatch_log_metric_filter)
目的: CloudWatch Logs から ERROR レベルのログを抽出し、メトリクスに変換
resource "aws_cloudwatch_log_metric_filter" "api_errors" {
name = "${var.name_prefix}-api-errors"
log_group_name = var.api_log_group_name
pattern = "{ $.level_name = \"ERROR\" }"
metric_transformation {
name = "APIErrorCount"
namespace = "${var.name_prefix}/Logs"
value = "1"
unit = "Count"
}
}
JSON パターンマッチングの詳細
Log Metric Filter は CloudWatch Logs から特定のパターンに一致するログを抽出し、メトリクスに変換します。
パターン { $.level_name = \"ERROR\" } は、JSON ログの level_name フィールドが "ERROR" と完全一致するログを抽出します。$ は JSON のルート要素を表し、\" は Terraform 内でダブルクォートをエスケープするための記法です。
実際のログ例とマッチング
{
"level_name": "ERROR",
"message": "request_error",
"context": {
"status": 500,
"exception": {
"class": "RuntimeException",
"message": "Database connection failed"
}
},
"datetime": "2025-10-21T03:07:31.263879+00:00"
}
{
"level_name": "ERROR",
"message": "job_error",
"context": {
"job": "sample_batch_job",
"exception": {
"class": "ApiException",
"message": "API rate limit exceeded"
}
},
"datetime": "2025-10-21T03:05:37.791542+00:00"
}
{
"level_name": "WARNING",
"message": "slow_query",
"context": {
"query_time": 2.5
},
"datetime": "2025-10-21T03:08:15.123456+00:00"
}
{
"level_name": "WARNING",
"message": "ERROR",
"context": {
"query_time": 2.5
},
"datetime": "2025-10-21T03:08:15.123456+00:00"
}
その他のパターン例:
# 厳密一致
{ $.level_name = "ERROR" }
# OR 条件
{ $.level_name = "ERROR" || $.level_name = "CRITICAL" }
# ワイルドカード
{ $.message = "database*" }
参考: より詳細なパターン構文については、公式ドキュメント – Filter pattern syntax を参照してください。
metric_transformation の設計
| パラメータ | 設定値 | 意味と選定理由 |
|---|---|---|
name |
"APIErrorCount" |
アラームで参照するメトリクスの識別子。 |
namespace |
"${var.name_prefix}/Logs" |
カスタムメトリクスの名前空間 |
value |
"1" |
カウント方式: マッチしたログ 1 件につきメトリクス値を 1 増加。Sum 統計で集計することでエラー総数を取得 |
unit |
"Count" |
単位の明示: メトリクスの単位を明示的に指定。CloudWatch Console での表示や、他のメトリクスとの比較に使用 |
b) CloudWatch Alarm (aws_cloudwatch_metric_alarm)
目的: メトリクスが閾値を超えた際に SNS Topic に通知を送信
resource "aws_cloudwatch_metric_alarm" "api_errors" {
alarm_name = "${var.name_prefix}-api-high-error-rate"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = var.evaluation_periods
metric_name = "APIErrorCount"
namespace = "${var.name_prefix}/Logs"
period = var.period_seconds
statistic = "Sum"
threshold = var.error_threshold
alarm_description = "API error count exceeded ${var.error_threshold} in ${var.period_seconds} seconds"
alarm_actions = [aws_sns_topic.alerts.arn]
ok_actions = var.notify_on_ok ? [aws_sns_topic.alerts.arn] : []
treat_missing_data = "notBreaching"
tags = {
Name = "${var.name_prefix}-api-high-error-rate"
Environment = var.env
Component = "API"
}
}
パラメータの解説
| パラメータ | 説明 | 設定値 |
|---|---|---|
alarm_name |
アラームの識別名。CloudWatch Console やログで表示される名前 | "${var.name_prefix}-api-high-error-rate" |
comparison_operator |
メトリクス値と閾値を比較する演算子 |
"GreaterThanOrEqualToThreshold" (以上) |
evaluation_periods |
何回連続で閾値を超えたらアラームを発火するか |
1 (即座に通知) |
metric_name |
監視対象のメトリクス名。Log Metric Filter で作成したメトリクスを参照 | "APIErrorCount" |
namespace |
メトリクスが属する名前空間。カスタムメトリクスは任意の名前空間を指定可能 | "${var.name_prefix}/Logs" |
period |
メトリクスの評価期間(秒)。この期間内でメトリクス値を集計 |
60 (1 分間) |
statistic |
メトリクスの集計方法 |
"Sum" (合計値) |
threshold |
アラームをトリガーする閾値 |
3 (3 個以上のエラー) |
alarm_description |
アラームの説明文。Slack 通知にも表示される | "API error count exceeded 3 in 60 seconds" |
alarm_actions |
ALARM 状態に遷移した時に実行するアクション(SNS Topic ARN) | [aws_sns_topic.alerts.arn] |
ok_actions |
OK 状態に復帰した時に実行するアクション |
[aws_sns_topic.alerts.arn] または [] (復旧通知の有無) |
treat_missing_data |
データが来ない場合の扱い。notBreaching = データ欠損時はアラームを発火しない(正常扱い) |
"notBreaching" |
閾値設計の考え方
CloudWatch Alarm は以下の条件で評価されます:
評価式: Sum(APIErrorCount) >= 3 errors in 60 seconds for 1 period
評価プロセス:
- 60 秒間にエラーログが 4 件発生
- Log Metric Filter が各ログをカウント(1 件 = 値 1)
- CloudWatch Metric が 60 秒間の合計を計算:
Sum = 4 - CloudWatch Alarm が閾値と比較:
4 >= 3→ ALARM 状態へ遷移 - SNS Topic にメッセージを発行 → Slack 通知
エラー数が閾値を下回ると(Sum < 3)、OK 状態に戻ります。
パラメータの関係性
| パラメータ | デフォルト値 | 意味 |
|---|---|---|
threshold |
3 |
閾値: この値以上でアラート |
period |
60 (秒) |
評価期間: この期間内でのメトリクス集計 |
evaluation_periods |
1 |
連続期間: 何回連続で閾値超過したらアラート |
statistic |
"Sum" |
集計方法: メトリクスの計算方法 |
comparison_operator |
"GreaterThanOrEqualToThreshold" |
比較演算子: 閾値との比較方法 |
alarm_actions と ok_actions の違い
| パラメータ | トリガー | 用途 |
|---|---|---|
alarm_actions |
OK → ALARM 遷移時 |
問題発生通知: エラーが閾値を超えたときに Slack 通知 |
ok_actions |
ALARM → OK 遷移時 |
復旧通知: エラーが閾値を下回り、正常に戻ったときに Slack 通知 |
insufficient_data_actions |
データ不足時 | データ欠損通知: Log Group が存在しない、データが来ないなどの異常検知 |
CloudWatch Alarm の 3 つの状態:
-
OK 状態 (初期状態)
- エラー数が閾値未満
-
ok_actions実行: 復旧通知を Slack に送信(設定により有効化) - Slack メッセージ例:
✅ 復旧しました
-
ALARM 状態
- エラー数が閾値以上(
Sum >= 3) -
alarm_actions実行: 問題発生通知を Slack に送信 - Slack メッセージ例:
🚨 API でエラー急増!
- エラー数が閾値以上(
-
INSUFFICIENT_DATA 状態
- Log Group が存在しない、またはデータが来ない
-
insufficient_data_actions実行可能(今回は未設定) - データ復旧後、自動的に OK 状態に戻る
状態遷移:
-
OK → ALARM: エラー数が閾値を超えた時 -
ALARM → OK: エラー数が閾値を下回った時 -
OK/ALARM → INSUFFICIENT_DATA: ログデータが途絶えた時 -
INSUFFICIENT_DATA → OK: ログデータが復旧した時
treat_missing_data の選択理由
| 設定値 | 動作 | 選択理由 |
|---|---|---|
"notBreaching" |
データがない = 正常 | ✅ この実装で選択: ログがない = エラーがない = 正常。深夜帯など API アクセスがない時間帯でも誤アラートを防止 |
"breaching" |
データがない = 異常 | アプリケーションが動作しているはずなのにログがない場合に使用。監視の監視が必要 |
"ignore" |
データがない = 評価しない | evaluation_periods が複数の場合に使用。今回は 1 なので不適切 |
"missing" |
データがない = INSUFFICIENT_DATA 状態 | 通知がうるさくなるため、今回は不要 |
c) SNS Topic (aws_sns_topic)
目的: CloudWatch Alarm からの通知を受け取り、AWS Chatbot に配信するメッセージハブ
resource "aws_sns_topic" "alerts" {
name = "${var.name_prefix}-alerts"
display_name = "CloudWatch Alerts for ${var.env}"
tags = {
Name = "${var.name_prefix}-alerts"
Environment = var.env
}
}
パラメータの詳細解説
| パラメータ | 設定値 | 目的・理由 |
|---|---|---|
name |
${var.name_prefix}-alerts |
SNS Topic の識別名 |
display_name |
CloudWatch Alerts for ${var.env} |
AWS Console や Slack 通知で表示される名前。環境を示す情報を含めておくとわかりやすい。 |
tags |
Name, Environment
|
コスト配分タグ、リソース識別、自動化スクリプトでの検索を可能にする |
d) SNS Topic Policy (aws_sns_topic_policy)
目的: CloudWatch Alarm が SNS Topic に Publish できるようにするアクセス許可ポリシー
resource "aws_sns_topic_policy" "alerts" {
arn = aws_sns_topic.alerts.arn
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowCloudWatchAlarmsPublish"
Effect = "Allow"
Principal = {
Service = "cloudwatch.amazonaws.com"
}
Action = "SNS:Publish"
Resource = aws_sns_topic.alerts.arn
},
{
Sid = "AllowChatbotSubscribe"
Effect = "Allow"
Principal = {
Service = "chatbot.amazonaws.com"
}
Action = [
"SNS:Subscribe",
]
Resource = aws_sns_topic.alerts.arn
}
]
})
}
Policy 内容の詳細
2 つの Statement で権限を分離:
| Statement ID | Principal (誰が) | Action (何を) | 目的 |
|---|---|---|---|
| AllowCloudWatchAlarmsPublish | CloudWatch サービス | SNS:Publish |
アラーム発生時にメッセージを送信 |
| AllowChatbotSubscribe | Chatbot サービス | SNS:Subscribe |
SNS Topic をサブスクライブ |
e) IAM Role for Chatbot (aws_iam_role)
目的: AWS Chatbot が CloudWatch のメトリクスやログ情報を取得するための権限付与
resource "aws_iam_role" "chatbot" {
name = "${var.name_prefix}-chatbot-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "chatbot.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
managed_policy_arns = [
"arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess"
]
tags = {
Name = "${var.name_prefix}-chatbot-role"
Environment = var.env
}
}
resource "aws_iam_role_policy" "chatbot" {
name = "${var.name_prefix}-chatbot-policy"
role = aws_iam_role.chatbot.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:GetLogEvents",
"logs:FilterLogEvents"
]
Resource = [
"arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${var.api_log_group_name}:*",
"arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${var.batch_log_group_name}:*"
]
}
]
})
}
f) AWS Chatbot Configuration (aws_chatbot_slack_channel_configuration)
目的: SNS からの通知を Slack チャネルに転送する設定
resource "aws_chatbot_slack_channel_configuration" "alerts" {
configuration_name = "${var.name_prefix}-slack-alerts"
iam_role_arn = aws_iam_role.chatbot.arn
slack_channel_id = var.slack_channel_id
slack_team_id = var.slack_workspace_id
sns_topic_arns = [
aws_sns_topic.alerts.arn
]
logging_level = "INFO"
tags = {
Name = "${var.name_prefix}-slack-alerts"
Environment = var.env
}
}
各パラメータの意味
| パラメータ | 説明 | 設定例 | バリデーション |
|---|---|---|---|
configuration_name |
Chatbot 設定の識別子 | myapp-dev-slack-alerts |
英数字とハイフン |
iam_role_arn |
Chatbot が使用する IAM Role | 上記で作成した Role の ARN | ARN 形式 |
slack_channel_id |
通知先 Slack チャネル ID | C0123456789 |
C で始まる英数字 |
slack_team_id |
Slack ワークスペース ID | T0123456789 |
T で始まる英数字 |
sns_topic_arns |
購読する SNS Topic のリスト | [aws_sns_topic.alerts.arn] |
ARN のリスト |
logging_level |
Chatbot のログレベル | INFO |
ERROR / INFO / NONE |
📦 Terraform モジュール構成
モジュールの依存関係
Monitoring モジュールが作成するリソース:
-
SNS Topic (
aws_sns_topic)- CloudWatch Alarm からの通知を受信
-
SNS Topic Policy (
aws_sns_topic_policy)- CloudWatch と Chatbot に SNS Topic へのアクセス権限を付与
-
Log Metric Filter (
aws_cloudwatch_log_metric_filter) × 2- API とバッチのエラーログを抽出してメトリクス化
-
CloudWatch Alarm (
aws_cloudwatch_metric_alarm) × 2- API とバッチのエラーメトリクスを監視
-
IAM Role (
aws_iam_role)- Chatbot が CloudWatch にアクセスするための権限
-
IAM Role Policy (
aws_iam_role_policy)- Chatbot 用の最小権限ポリシー
-
Chatbot Configuration (
aws_chatbot_slack_channel_configuration)
リソース間の参照関係:
- CloudWatch Alarm → SNS Topic (通知先)
- Chatbot Configuration → SNS Topic (サブスクリプション)
- Chatbot Configuration → IAM Role (権限)
- Log Metric Filter → CloudWatch Alarm (メトリクス名)
variables.tf の設計思想
variable "name_prefix" {
type = string
description = "Prefix for resource names"
}
variable "env" {
type = string
description = "Environment name (dev/prd)"
}
variable "api_log_group_name" {
type = string
description = "CloudWatch Log Group name for API"
}
variable "batch_log_group_name" {
type = string
description = "CloudWatch Log Group name for Batch"
}
variable "error_threshold" {
type = number
description = "Error count threshold for alarms"
default = 3
}
variable "evaluation_periods" {
type = number
description = "Number of periods to evaluate"
default = 1
}
variable "period_seconds" {
type = number
description = "Period in seconds for metric evaluation"
default = 60
}
variable "slack_workspace_id" {
type = string
description = "Slack Workspace ID (Team ID) for AWS Chatbot integration"
sensitive = true
validation {
condition = can(regex("^T[A-Z0-9]{8,}$", var.slack_workspace_id))
error_message = "Slack Workspace ID must start with 'T' followed by at least 8 alphanumeric characters"
}
}
variable "slack_channel_id" {
type = string
description = "Slack Channel ID for notifications"
sensitive = true
validation {
condition = can(regex("^C[A-Z0-9]{8,}$", var.slack_channel_id))
error_message = "Slack Channel ID must start with 'C' followed by at least 8 alphanumeric characters"
}
}
variable "notify_on_ok" {
type = bool
description = "Send Slack notifications when alarms return to OK state"
default = true
}
- slack_team_id、slack_channel_id については
sensitive = trueでマスキング
設定値は Terraform Cloud の変数に登録し、apply 時に設定される様にしています。
🚀 実装手順
1. AWS Chatbot の事前準備(必須)
重要: Terraform apply の前に、AWS Console で Slack OAuth 認証を完了する必要があります。
やり忘れると、Terraform apply で Chatbot へ Slack チャンネルの登録で失敗します。
失敗しても認証完了後に再度 apply を実行すれば成功します。
認証手順
-
Chatbot のページを開き、右側の「チャットクライアントの選択」で Slack を選択し、その下の「クライアントを設定」ボタンクリック

-
Slack のワークスペースに「Amazon Q Developer」のインストールを要求されるので許可

2. Terraform 変数の設定
terraform.tfvars の作成
name_prefix = "myapp-dev"
env = "dev"
api_log_group_name = "/ecs/api"
batch_log_group_name = "/ecs/batch"
error_threshold = 3
evaluation_periods = 1
period_seconds = 60
notify_on_ok = true
3. Terraform Apply
Dev 環境での検証
terraform init -upgrade
terraform plan
terraform apply
4. 動作確認方法
Step 0: 事前準備 – Slack チャンネルへAmazonQの招待
AWS Chatbot が Slack チャンネルにメッセージを投稿するためには、対象のチャンネルに Amazon Q Developer を招待する必要があります。
Slack の対象チャンネルで以下のコマンドを実行してください。
Step 1: アラームを生成
- メトリクスを選択
Terraformで作成されたメトリクスAPIErrorCountを選択します。Slackに通知が届くことを確認できれば良いので何を選んでも良いです。 - 期間を「10秒」に変更
- 条件:しきい値は静的、アラームの条件は「より低い」、しきい値は「1」
- その他の設定で欠損データの処理を「欠落データを不正 (しきい値を超えている)として処理」を選択

- 通知設定で、先ほど作成した SNS トピックを選択し、アラームを作成します。
Step 2: Slack 通知の確認
この状態で10秒ちょっと待つとアラート状態になり、SNSトピック、Chatbotを経由し、Slack に通知が届きます。
🚨 CloudWatch Alarm | {作成したアラーム名} | ap-northeast-1 | Account: {アカウントID}
Threshold Crossed: no datapoints were received for 1 period and 1 missing datapoint was treated as [Breaching].
Namespace
sentinel-dev/Logs
Metric
BatchErrorCount
Timestamp
Tue, 28 Oct 2025 06:29:47 UTC
Alarm State
ALARM
Step 3: アラームの復旧確認
先ほど作成したアラームの条件を以下のように変更し、OK 状態に復帰させます。
- その他の設定:欠損データの処理を「欠落データを適正 (しきい値を超えていない)として処理」を選択し、アラームを保存
アラームがOKに変わり、復旧通知が届きます。
✅ CloudWatch Alarm | {作成したアラーム名} | ap-northeast-1 | Account: {アカウントID}
Threshold Crossed: no datapoints were received for 1 period and 1 missing datapoint was treated as [NonBreaching].
Namespace
myapp/Logs
Metric
hErrorCount
Timestamp
Tue, 28 Oct 2025 06:56:36 UTC
Alarm State
OK
⚠️ ハマりポイントと解決策
1. AWS Provider バージョン問題
問題
Error: Invalid resource type
│
│ on main.tf line 67, in resource "aws_chatbot_slack_channel_configuration" "alerts":
│ 67: resource "aws_chatbot_slack_channel_configuration" "alerts" {
│
│ The provider hashicorp/aws does not support resource type "aws_chatbot_slack_channel_configuration".
原因
aws_chatbot_slack_channel_configuration は AWS Provider v5.61.0 で追加されました。
プロバイダーのバージョンが古いと認識されません。
解決策
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.61.0"
}
}
}
2. SNS トピックのポリシー設定不足
問題
SNSトピックのポリシーを厳しくしすぎて、CloudWatch Alarm や Chatbot がアクセスできない場合があります。
Terraform自体は成功するものの、Slack に通知が届かない。
解決策
SNSトピックポリシーに以下の2つのStatementが含まれていることを確認してください。
- CloudWatch Alarm が SNS トピックに Publish できる権限
- Chatbot が SNS トピックを Subscribe できる権限
3. Chatobot側のSlack 認証忘れ
問題
Slack 認証前に terraform apply すると以下のエラー:
Error: error creating Chatbot Slack Channel Configuration: InvalidParameterException:
Slack workspace T0123456789 is not authorized
原因
Terraform は Slack OAuth 認証を自動化できません。手動での認証が必須です。
解決策
必須の事前作業: Terraform Apply 前に AWS Console から Slack 認証が必要です。
手順:
- AWS Chatbot Console を開く
- “Configure a chat client” → “Slack” → “Configure client”
- Slack 認証画面で “許可する”
- 認証完了後、Terraform apply
4. Slack チャンネルへの Amazon Q 招待忘れ
問題
SlackワークスペースにAmazon Q Developerをインストールしただけでは、通知が届きません。
AWS Chatbot が Slack チャンネルにメッセージを投稿するためには、対象のチャンネルに Amazon Q Developer を招待する必要があります。
Slack の対象チャンネルで以下のコマンドを実行してください。
5. JSON パターンマッチングのデバッグ
問題
Log Metric Filter が期待通りにマッチしない:
pattern = "{ $.level_name = ERROR }"
原因
JSON 文字列にはエスケープが必要です。
解決策
pattern = "{ $.level_name = \"ERROR\" }"
デバッグ方法
AWS CLI でパターンをテスト:
aws logs filter-log-events \
--log-group-name /ecs/api \
--filter-pattern '{ $.level_name = "ERROR" }' \
--limit 5
期待される出力:
{
"events": [
{
"logStreamName": "ecs/api/container-1",
"timestamp": 1729568851263,
"message": "{\"level_name\":\"ERROR\",\"message\":\"test_error\"}",
"ingestionTime": 1729568851500,
"eventId": "12345678901234567890"
}
],
"searchedLogStreams": [...]
}
マッチしない場合のチェックリスト:
| 確認項目 | 確認方法 |
|---|---|
| ログが JSON 形式か |
aws logs get-log-events で実際のログを確認 |
| フィールド名が一致するか |
level_name vs levelName の違いに注意 |
| 値が厳密一致するか |
ERROR vs Error の大文字小文字 |
| エスケープが正しいか |
\"ERROR\" とダブルクォートをエスケープ |
🎓 まとめ
本記事では、AWS Chatbot と Terraform を活用して、CloudWatch Logs のエラーログを Slack に通知する監視基盤を構築する方法を解説しました。
権限絞りすぎて通知が届かない、Chatbot の Slack 認証忘れなど、ハマりポイントも多いですが、一つ一つ丁寧に対処すれば確実に構築できます。
📚 参考資料
Source link
コメント