CloudWatch 入門 — ログ / メトリクス
CloudWatch Logs / Metrics / Alarms / Dashboards の構造、ロググループと retention、Metric Filter、Logs Insights クエリの基礎まで — すべての運用の目となる観測ツールを整理します。
第2章 から 第6章 までで AWS セットアップの基盤が集まりました。アカウント、IAM、コスト、CLI、SSO、セキュリティ — コンソールに入る前の頭の中の地図と日常のセットアップがひと通り整いました。いよいよ運用のもう一つの軸、何がどこで何をしているかを見る道具を扱います。
CloudWatch は AWS の観測(Observability)の標準です。AWS の中のほぼすべてのサービスがデフォルトでメトリクスを CloudWatch へ送り、ログも CloudWatch Logs が受け取ります。運用の最初の視界はここから始まります。
本章は1部の最後の章として、CloudWatch の4つの構成 — Logs / Metrics / Alarms / Dashboards — を整理します。より深い観測は 第26章 モニタリングと X-Ray で分散トレーシングとともに続きます。
大きな絵 — CloudWatch の4つの構成 #
| 構成要素 | 何か | よくある使いどころ |
|---|---|---|
| Logs | テキストログの保存 / 検索 | EC2 / Lambda / ECS / API Gateway のログ |
| Metrics | 時系列の数値 (CPU%、リクエスト数など) | すべての AWS サービスが自動送信 |
| Alarms | メトリクスがしきい値を超えると通知 / アクション | 運用通知、自動スケール |
| Dashboards | グラフ / ウィジェットのページ | チーム / サービス別の一覧表示 |
この4つはログ → メトリクス → アラーム → ダッシュボードの順につながります。
CloudWatch Logs #
ロググループとログストリーム #
Log Group — 通常は一つのアプリケーション / サービス単位
└── Log Stream — 通常は一つのプロセス / コンテナ単位
└── Log Event — 1行| 項目 | 例 |
|---|---|
| Log Group | /aws/lambda/my-function, /ecs/my-service, /var/log/myapp |
| Log Stream | Lambda 実行環境 ID、ECS Task ID、EC2 インスタンス ID |
| Log Event | 1行のテキスト + timestamp |
Lambda と ECS Fargate は自動でログを CloudWatch Logs へ送ります。EC2 は CloudWatch Agent または補助ツール(fluent-bit など)が必要です。
Retention — 最も重要な設定 #
デフォルトの retention は永久です。そのまま置くとログが永遠に溜まって費用が暴走します。登録直後、そして新しいロググループごとに retention を定める必要があります。
| 項目 | 推奨 retention |
|---|---|
| 一般アプリケーションのログ | 30 ~ 90日 |
| デバッグ / 開発のログ | 7日 |
| セキュリティ / 監査のログ (CloudTrail) | 1 ~ 7年 (S3 へ送る方が安い) |
| Lambda のログ | 14 ~ 30日 |
aws logs put-retention-policy \
--log-group-name /aws/lambda/my-function \
--retention-in-days 30aws logs describe-log-groups --query 'logGroups[].logGroupName' --output text \
| tr '\t' '\n' \
| while read name; do
aws logs put-retention-policy --log-group-name "$name" --retention-in-days 30
doneこの設定一つで CloudWatch のコスト事故の半分以上を防げます(第3章 コスト管理 のログ暴走の事故も、この設定で解消されます)。
新しいロググループの自動 retention #
新しく作られるロググループに自動で retention を適用する方法は2つあります。一つ目は EventBridge + Lambda で、CreateLogGroup イベントを受けて自動適用する方式で、実戦でよく使います。二つ目はポリシーで強制して、作るときに retention を明示しなければ拒否する方式ですが、少し強めです。
Lambda のログを送る #
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def handler(event, context):
logger.info("Received event: %s", event)
return {"ok": True}stdout / stderr が自動で CloudWatch Logs へ流れます。ロググループの名前は /aws/lambda/<関数名> です。
EC2 / ECS — CloudWatch Agent #
EC2 は自動ではありません。CloudWatch Agent のインストールが必要です。
sudo yum install -y amazon-cloudwatch-agent # AL
# または
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb設定ファイルは /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json です。
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/myapp/*.log",
"log_group_name": "/myapp/server",
"log_stream_name": "{instance_id}",
"retention_in_days": 30
}
]
}
}
},
"metrics": {
"metrics_collected": {
"mem": { "measurement": ["mem_used_percent"] },
"disk": { "measurement": ["used_percent"], "resources": ["*"] }
}
}
}ECS の Fargate はコンテナ定義に awslogs ドライバーを書けば自動です。これは 第15章 ECS と Fargate で詳しく扱います。
Logs Insights — クエリで検索 #
CloudWatch Logs の検索 / 分析ツールです。SQL に似た独自の文法を使います。
fields @timestamp, @message
| sort @timestamp desc
| limit 100fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 50fields @timestamp, @duration
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), count(*) by bin(5m)fields @timestamp, status, path
| filter status >= 500
| stats count(*) as errors by path
| sort errors descよく使うコマンドは次のとおりです。
| コマンド | 何か |
|---|---|
fields | 表示するフィールド |
filter | 条件フィルター |
parse | 文字列からフィールドを抽出 |
stats | 集計 (count, avg, max, percentile) |
sort | ソート |
limit | 最大結果数 |
bin(5m) | 時間バケット |
Logs Insights の費用に注意 #
クエリ時にスキャンしたデータの GB あたり課金されます(~$0.005/GB)。大きなロググループを無制限の時間でクエリすると費用事故が起こります。常に時間範囲を狭く取ります。
CloudWatch Metrics #
メトリクスは時系列の数値です。AWS のほぼすべてのサービスが自動送信します。
よく見るメトリクス #
| サービス | よく見るメトリクス |
|---|---|
| EC2 | CPUUtilization, NetworkIn/Out, DiskReadOps |
| RDS | CPUUtilization, DatabaseConnections, FreeStorageSpace, ReadLatency |
| Lambda | Invocations, Errors, Duration, Throttles, ConcurrentExecutions |
| ECS | CPUUtilization, MemoryUtilization (Service / Task 別) |
| ALB | RequestCount, TargetResponseTime, HTTPCode_Target_5XX_Count |
| API Gateway | Count, Latency, 4XXError, 5XXError |
| S3 | BucketSizeBytes, NumberOfObjects (1日1回) |
| DynamoDB | ConsumedReadCapacity/WriteCapacity, ThrottledRequests |
メトリクスのディメンション (Dimensions) #
同じメトリクスでもディメンションで分解されます。
Service: AWS/EC2
Metric: CPUUtilization
Dimensions:
- InstanceId: i-1234567890
- InstanceId: i-2345678901
- InstanceId: i-3456789012ディメンションが異なれば別のメトリクスです。メトリクスの数がすなわち費用なので、ディメンションが爆発すると費用事故が起こります。
統計 (Statistic) #
| 統計 | 何か |
|---|---|
Sum | 合計 — Invocations、RequestCount |
Average | 平均 — CPU、Latency |
Maximum | 最大 — Spike 検知 |
Minimum | 最小 |
p95 / p99 | パーセンタイル — Latency |
SampleCount | データポイントの数 |
ほとんどの場合、Average + p95 が意味を持ちます。p99 / p99.9 は SLA とユーザー体験に直接影響を与えます。
標準 vs 高解像度 #
| 種類 | 解像度 | 費用 |
|---|---|---|
| 標準 | 1分 | 標準 |
| 高解像度 | 1秒 | 高価 — スパイクが短い場合だけ |
ほとんど標準1分で十分です。
カスタムメトリクスを送る #
アプリケーションが直接送信します。
import boto3
cloudwatch = boto3.client("cloudwatch")
cloudwatch.put_metric_data(
Namespace="MyApp",
MetricData=[{
"MetricName": "OrderCreated",
"Value": 1,
"Unit": "Count",
"Dimensions": [
{"Name": "Environment", "Value": "prod"},
{"Name": "Region", "Value": "ap-northeast-2"},
],
}],
)費用はメトリクスあたり $0.30 / 月で、ディメンションの組み合わせごとに別です。ユーザー ID のような高カーディナリティのディメンションは絶対に禁止します。
EMF (Embedded Metric Format) — Lambda 用のパターン #
Lambda では put_metric_data の呼び出し自体が費用と遅延の負担です。ログに特定の JSON 形式で書くと、CloudWatch が自動でメトリクスに変換します。
import json
print(json.dumps({
"_aws": {
"Timestamp": int(time.time() * 1000),
"CloudWatchMetrics": [{
"Namespace": "MyApp",
"Dimensions": [["Environment"]],
"Metrics": [{"Name": "OrderCreated", "Unit": "Count"}],
}],
},
"Environment": "prod",
"OrderCreated": 1,
}))aws-embedded-metrics-python のような SDK がこれをよりきれいに助けてくれます。
Metric Filter — ログからメトリクスを作る #
すでにログにある情報(ERROR の発生、応答時間など)をメトリクスに変換します。
CloudWatch → Log groups → グループを選択 → Metric filters → Create
- Filter pattern: ERROR
- Metric namespace: MyApp
- Metric name: ErrorCount
- Metric value: 1これで ERROR が一度発生するたびにメトリクスが +1 されます。アラームやダッシュボードに活用できます。
ERROR # ERROR の単語を含む
[..., level="ERROR", ...] # 構造化ログのフィールド
{ $.level = "ERROR" } # JSON ログのキーCloudWatch Alarms #
メトリクスがしきい値を超えるとアクションをします。通知の本拠地です。
最初のアラーム — Lambda Errors #
CloudWatch → Alarms → Create alarm
- Metric: AWS/Lambda → Errors → Function: my-function
- Statistic: Sum
- Period: 1 minute
- Threshold: > 0 for 1 datapoint within 5 minutes
- Action: SNS → 通知トピック
- Name: lambda-my-function-errorsAlarm の状態 #
| 状態 | 意味 |
|---|---|
OK | しきい値内 |
ALARM | しきい値超過 — アクション発生 |
INSUFFICIENT_DATA | データ不足 — 新しく作った場合 / メトリクスが来ない |
INSUFFICIENT_DATA をアラーム処理(通知)するかは任意です。新しいアラームの評価中によく出る状態なので、一般的には無視します。
Composite Alarms #
複数のアラームの AND / OR で組み合わせます。「ALB 5xx ≥ 1% AND CPU > 80%」のようなパターンです。
ALARM("alb-5xx") AND ALARM("ec2-high-cpu")誤検知を減らすのに効果的です。
Alarm アクション #
| アクション | 何か |
|---|---|
| SNS Topic | メール / Slack / SMS / Lambda などへ fanout |
| EC2 Action | インスタンスの stop / terminate / reboot / recover |
| Auto Scaling | ASG のスケール in / out |
| Systems Manager | OpsItem を作る |
運用通知の大半は SNS → Slack / メールです。
Anomaly Detection #
基準線(band)を自動で学習した後、その外ならアラームを出します。トラフィックや CPU のようにパターンのあるメトリクスに効果的で、静的なしきい値より誤検知が少ないです。
SNS 統合 — 通知を送る方法 #
ほとんどのアラームが SNS Topic へ行き、そこから次の段階へ fanout します。
| サブスクリプション | どこへ |
|---|---|
| メール | |
| HTTPS | Slack incoming webhook |
| Lambda | 加工後に別の段階 |
| SMS | 携帯電話 (まれに) |
| SQS | キューへ |
Slack 連携 — Lambda パターン #
直接 webhook で送るか、AWS Chatbot で送ります。
import json, os, urllib.request
WEBHOOK = os.environ["SLACK_WEBHOOK"]
def handler(event, context):
msg = json.loads(event["Records"][0]["Sns"]["Message"])
payload = json.dumps({
"text": f"🚨 *{msg['AlarmName']}* — {msg['NewStateValue']}",
"blocks": [...]
}).encode()
req = urllib.request.Request(WEBHOOK, data=payload,
headers={"Content-Type": "application/json"})
urllib.request.urlopen(req)第18章 API Gateway と Lambda と 第19章 EventBridge / SQS / SNS でより深く扱います。
CloudWatch Dashboards #
ウィジェットのページです。チーム / サービス別の一覧表示に使います。JSON で定義してコードで管理できます。
よく作るダッシュボード #
| 種類 | 何か |
|---|---|
| サービスダッシュボード | 一つのサービスの核心メトリクス (リクエスト、遅延、エラー、インフラ) |
| インフラダッシュボード | EC2/RDS の CPU / メモリ / ネットワーク |
| ビジネスダッシュボード | 登録 / 決済 / 注文のようなビジネスメトリクス |
| オンコールダッシュボード | アクティブなアラーム / 最近の事故 / 核心指標 |
ウィジェットの種類 #
- メトリクスグラフ(line、stacked、number)
- ログ(Logs Insights クエリの結果)
- テキスト(Markdown — ダッシュボードの案内)
- Alarm status
良いダッシュボードは「この1ページを30秒見ればシステムの状態が分かる」になることです。
登録直後にオンにすべき設定 #
1部が終わる時点では、次の設定が揃っているべきです。
| 項目 | どこで |
|---|---|
| 新しいロググループに retention を自動適用 | コンソール / EventBridge + Lambda |
| Lambda Errors アラーム | 関数ごと |
| RDS FreeStorageSpace アラーム | DB ごと |
| ALB 5xx アラーム | LB ごと |
| ビリングアラーム (第3章 コスト管理) | アカウント単位 |
| GuardDuty findings アラーム (第6章 セキュリティ基本) | アカウント単位 |
この6つが小さな運用の通知基盤です。
よく出会う落とし穴 #
- ログの retention が永久 — 最もよくある費用事故です。ロググループごとに retention を明示し、新しいグループは自動化します。この設定一つで費用を半分以上節約できます。
- 高カーディナリティのカスタムメトリクス —
Dimensions: [{Name: 'UserId', Value: user_id}]のようにすると、ユーザー1万人のときメトリクス1万個 × ディメンションの組み合わせで1ヶ月 $3000+ になります。ユーザー別はログ(Logs Insights)が答えです。 - Logs Insights の無制限の時間クエリ — 大きなロググループに時間範囲を定めないと GB 単位のスキャン費用がかかります。常に時間範囲を狭く取ります。
- Alarm の Period が短すぎる — 1分1データポイントでアラームをかけると、一時的な spike のたびにアラームが暴走します。通常は5分 / 3データポイント程度がノイズを適度に減らします。
- Alarm アクションを付けない — アラームを作って SNS やアクションを付けないと、コンソールでだけ赤くなります。誰も知りません。作るときにアクションを一緒に付けます。
- ダッシュボードだけ作って見ない — 作った直後は全員見ますが、時間が経つと忘れられます。オンコールや日々のスタンドアップの最初のチェック項目として定着させます。
- Metric Math の未使用 — 複数のメトリクスの比率 / 合計 / 変換を計算できる Metric Math があります。「5xx / 総リクエスト = エラー率」のような計算です。うまく使えばダッシュボードとアラームがずっときれいになります。
練習問題 #
- §「Retention — 最も重要な設定」の一括適用スクリプトを自分の環境で dry-run として読んでみて、この設定が 第3章 コスト管理 の「ログの暴走」の事故をどう防ぐかを一段落で説明してみましょう。
- §「CloudWatch Metrics」のよく見るメトリクスの表で Lambda と ALB の行を選び、それぞれどのメトリクスにアラームをかければ最初の運用事故を捕まえられるかを §「登録直後にオンにすべき設定」の表と結びつけて書いてみましょう。
- §「高カーディナリティのカスタムメトリクス」の落とし穴を根拠に、ユーザー別の注文数を追跡したいときにカスタムメトリクスの代わりに Logs Insights を使うべき理由を費用の観点から説明してみましょう。
一行まとめ: CloudWatch は Logs · Metrics · Alarms · Dashboards の4構成で運用の目となり、ログからダッシュボードまで一続きでつながります。ログの retention を明示しなければ費用が暴走するので、登録直後の設定が必須です。メトリクスはディメンションの数がそのまま費用なので高カーディナリティのディメンションを禁止し、アラームは SNS アクションを必ず付けてこそ意味があります。
次の章 #
これで1部「AWS のはじまり」が終わりました。コンソール / アカウント / IAM / コスト / CLI / SSO / セキュリティ / CloudWatch — AWS の上で何かを始めるのに必要な道具箱がひとまとまりになりました。いよいよ本物のリソースを作る番です。2部の最初の章である 第8章 EC2 と VPC では、仮想マシン EC2 と、その EC2 が住む仮想ネットワーク VPC — Subnet / Internet Gateway / Route Table / Security Group / NACL — の構造を一筋に整理します。