- AWS
CloudWatch Logs Insightsのクエリ集|エラー・遅いリクエスト
CloudWatch Logs Insights は、CloudWatch Logs のロググループに対して、fields・filter・stats などをパイプ(|)でつないだクエリを実行し、ログを検索・集計する機能です。 料金は「スキャンした(圧縮前の)ログの量」で決まるため、時間の範囲とロググループを絞るほど安く・速くなります。
# 直近のエラーを新しい順に 50 件
fields @timestamp, @logStream, @message
| filter @message like /(?i)(error|exception)/
| sort @timestamp desc
| limit 50
| 目的 | このページのクエリ |
|---|---|
| エラーの件数を時間ごとに | 「エラー・例外」 |
| Lambda の遅い呼び出し、Duration の p95 | 「Lambda の REPORT 行」 |
| メモリの割り当てすぎ・足りなさ | 同上(@maxMemoryUsed) |
| コールドスタートの割合 | 同上(@initDuration) |
| タイムアウトした呼び出し | REPORT 行の Status: timeout |
| API Gateway の 5xx・遅いパス | 「API Gateway のアクセスログ」 |
| 1つのリクエストのログを全部 | 「リクエストID・相関ID」 |
確認環境:クエリの構文・関数・自動で見つかるフィールド・上限は Amazon CloudWatch Logs のドキュメントで確認しました。Lambda の REPORT 行を取り出す parse の正規表現は、Python 3.11 の re で、ドキュメントに載っている REPORT 行(スペース区切り・Init Duration あり・Status: timeout あり)と、タブ区切りの行に当てて結果を確かめました。CLI(start-query・get-query-results)と boto3 のコードは、AWS CLI 1.46.1・boto3 1.43.112 を moto 5.2.4 のサーバーモードに向けて動かしています(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CloudWatch Logs Insightsのクエリ集|エラー・遅いリクエスト」
構文の早見表
コマンド
| コマンド | すること | 例 |
|---|---|---|
fields |
表示する項目を選ぶ。計算した項目も作れる | fields @timestamp, @message, @duration / 1000 as sec |
display |
最後に表示する項目だけを決める | display @timestamp, msg |
filter |
条件に合うログだけ残す | filter level = "ERROR" and status >= 500 |
stats |
集計する(by でグループ分け) |
stats count(*) by bin(5m) |
sort |
並べ替え(asc/desc) |
sort @timestamp desc |
limit |
返す件数 | limit 100 |
parse |
文字列から項目を取り出す(ワイルドカードか正規表現) | parse @message "user=* " as user |
dedup |
指定した項目の値が同じものを1件にする | dedup @requestId |
unnest |
配列を1要素1行に展開する | unnest json_message.events into event |
unmask |
データ保護でマスクされた内容を表示(権限が要る) | ― |
filterIndex |
フィールドインデックスがあるロググループだけを読む | filterIndex IPaddress = "198.51.100.0" |
pattern |
ログを似た形ごとにまとめる | filter @message like /ERROR/ | pattern @message |
diff |
同じ長さの前の期間と比べる | ― |
SOURCE |
名前の前方一致やタグでロググループを選ぶ(CLI・API だけ) | SOURCE logGroups(namePrefix: ['/aws/lambda/']) |
ドキュメントのコマンド一覧には、このほか anomaly・lookup・join・where(filter の別名)・estimate(スキャン量の見積もり)なども載っています。
filter の比較・文字列の一致
| 書き方 | 意味 |
|---|---|
=・!=・<・<=・>・>= |
比較 |
and・or・not |
条件の組み合わせ |
like "Exception" |
部分一致(大文字・小文字を区別) |
like /Exception/・=~ /Exception/ |
正規表現で部分一致 |
like /(?i)exception/ |
大文字・小文字を区別しない |
not like "health" |
含まない |
in ["GET", "POST"]・not in [...] |
どれかと完全一致 |
ispresent(field) |
項目がある |
isempty(field) |
項目が無いか空文字(1 を返す) |
ドキュメントには、filter 項目 like はインデックスを使わず、選んだロググループの全ログを読むと書かれています。
stats の集計関数
| 関数 | 意味 |
|---|---|
count(*)・count(field) |
件数。count(field) はその項目があるログだけ数える |
countDistinct(field) |
値の種類の数(種類がとても多いと近似値) |
sum・avg・min・max |
合計・平均・最小・最大 |
pct(field, 95) |
パーセンタイル(p95 なら、95% がこの値より小さい) |
stddev・variance |
標準偏差・分散 |
values(field) |
グループごとの値の一覧 |
topk(10, field) |
多い値の上位 k 個(by と一緒に使えない) |
earliest(field)・latest(field) |
時刻がいちばん前・後のログの値(集計ではない関数) |
| stats の決まり(ドキュメント) | 内容 |
|---|---|
1つのクエリの stats |
10 個まで |
sort・limit |
最後の stats より後に書く |
bin(5m) |
@timestamp を 5 分ごとに区切る。単位は ms・s・m・h・d・w・mo・q・y |
よく使う関数
| 関数 | 使い方 |
|---|---|
bin(1h) |
時間ごとの集計 |
coalesce(a, b, 0) |
最初の空でない値(無い項目を 0 にする) |
concat・replace・toupper・strlen |
文字列の操作 |
jsonParse(field) |
JSON の文字列を、項目として読めるようにする |
datefloor・dateceil |
時刻の切り捨て・切り上げ |
abs・ceil・floor |
数値 |
自動で使える項目(フィールド)
| ログ | 項目(ドキュメント) |
|---|---|
| すべて | @timestamp・@message・@ingestionTime・@logStream・@log(アカウントID:ロググループ名) |
| Lambda | @requestId・@type・@duration・@billedDuration・@memorySize・@maxMemoryUsed(X-Ray のトレースIDがあれば @xrayTraceId・@xraySegmentId) |
| JSON のログ | キーがそのまま項目になる。入れ子は a.b.c、配列は items.0.id。1件から 200 項目まで |
コールドスタートの初期化時間 @initDuration は、上の一覧には無いものの、Lambda のドキュメントのクエリ例(SnapStart など)で使われています。@duration・@initDuration はミリ秒、@memorySize・@maxMemoryUsed はバイトで入っているため、ドキュメントの例では MB にするとき / 1000 / 1000 しています。
エラー・例外を探す
エラーのログを新しい順に
fields @timestamp, @logStream, @message
| filter @message like /(?i)(error|exception|traceback)/
| sort @timestamp desc
| limit 100
エラーの件数を5分ごとに数える
filter @message like /(?i)error/
| stats count(*) as errors by bin(5m)
by bin(...) で集計すると、コンソールの「可視化」タブで折れ線グラフになります。ダッシュボードに追加もできます。
JSON ログ(構造化ログ)のエラーを種類ごとに
filter level = "ERROR"
| stats count(*) as n by exception_name, service
| sort n desc
level・exception_name は、Powertools の Logger が出す JSON のキーです。JSON のログでは、キーをそのまま filter・stats に使えます。出力するキーの設計は、関連記事「構造化ログ(JSON)設計|必須フィールド一覧とPython・Node実装例」で扱っています。
Python の例外の種類を数える(テキストのログ)
filter @message like /\[ERROR\]/
| parse @message /\[ERROR\] (?<errType>[A-Za-z_.]+(Error|Exception))/
| stats count(*) as n by errType
| sort n desc
Lambda の Python ランタイムは、捕まえなかった例外を [ERROR] ValueError: ... の形でログに出します。
タイムアウト・メモリ不足
filter @message like /Task timed out after/
or @message like /Runtime exited with error: signal: killed/
or @message like /Status: timeout/
| fields @timestamp, @logStream, @message
| sort @timestamp desc
タイムアウトの原因の切り分けは、関連記事「Task timed out afterの直し方|Lambdaタイムアウト原因別」で扱っています。
Lambda の REPORT 行を集計する
Lambda は呼び出しごとに、次のような REPORT 行を出します(Lambda のドキュメントの例)。
REPORT RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 Duration: 15.74 ms Billed Duration: 147 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 130.49 ms
XRAY TraceId: 1-5e34a614-10bdxmplf1fb44f07bc535a1 SegmentId: 07f5xmpl2d1f6f85 Sampled: true
| 項目(ドキュメント) | 意味 |
|---|---|
| Duration | ハンドラが処理にかけた時間 |
| Billed Duration | 課金の対象になった時間 |
| Memory Size | 割り当てたメモリ |
| Max Memory Used | 使ったメモリの最大。実行環境を使い回すと、それまでの呼び出しの最大になる |
| Init Duration | 最初のリクエストだけ。ランタイムの起動とハンドラの外のコードの時間(コールドスタート) |
| Status | タイムアウトなどで終わったときに付く(例:Status: timeout) |
テキスト形式のログでは、filter @type = "REPORT" だけで @duration などが使えます。 parse を書かずに済みます。
Duration の p50・p95・p99 と最大
filter @type = "REPORT"
| stats count(*) as invocations,
avg(@duration) as avgMs,
pct(@duration, 50) as p50Ms,
pct(@duration, 95) as p95Ms,
pct(@duration, 99) as p99Ms,
max(@duration) as maxMs
by bin(1h)
平均だけでは、一部の遅い呼び出しが隠れます。p95・p99 を見ると、利用者の何割が遅さを感じているかが分かります。
遅い呼び出しを一覧で(再試行の重複を除く)
fields @timestamp, @requestId, @duration, @logStream
| filter @type = "REPORT" and @duration > 1000
| sort @duration desc
| dedup @requestId
| limit 20
ドキュメントの例をもとに、遅い順に並べています。dedup @requestId で、再試行で同じリクエストIDが何度も出たものを1件にします。
メモリの割り当てすぎ・足りなさ
filter @type = "REPORT"
| stats max(@memorySize / 1000 / 1000) as allocatedMB,
avg(@maxMemoryUsed / 1000 / 1000) as avgUsedMB,
max(@maxMemoryUsed / 1000 / 1000) as maxUsedMB,
allocatedMB - maxUsedMB as unusedMB
| 結果の見方 | 判断の目安 |
|---|---|
maxUsedMB が allocatedMB に近い |
メモリ不足で落ちる手前。割り当てを増やす |
unusedMB が大きい |
割り当てを減らせる。ただし Lambda は CPU もメモリに比例するため、減らすと遅くなることがある |
コールドスタートの割合と初期化時間
filter @type = "REPORT"
| stats count(*) as invocations,
count(@initDuration) as coldStarts,
coldStarts * 100 / invocations as coldPct,
avg(@initDuration) as avgInitMs,
max(@initDuration) as maxInitMs
by bin(1h)
count(@initDuration) は、Init Duration がある(=コールドスタートの)REPORT 行だけを数えます。対策は、関連記事「Lambdaコールドスタート対策|SnapStartとプロビジョンド同時実行の比較」で扱っています。
関数ごとに比べる(複数のロググループ)
filter @type = "REPORT"
| parse @log /\d+:\/aws\/lambda\/(?<function>.*)/
| stats count(*) as n, pct(@duration, 95) as p95Ms, max(@maxMemoryUsed / 1000 / 1000) as maxMB
by function
| sort p95Ms desc
@log は 123456789012:/aws/lambda/関数名 の形なので、そこから関数名を取り出します(Lambda のドキュメントの SnapStart の例と同じ書き方)。
parse で REPORT 行を取り出す(JSON 以外のログ・自前の集計用)
@duration などを使えないとき(ログを別のロググループに転送した、Lambda 以外の場所で同じ形式を扱う、など)は、parse の正規表現で取り出します。
filter @message like /^REPORT/
| parse @message /REPORT RequestId: (?<rid>\S+)\s+Duration: (?<dur>[\d.]+) ms\s+Billed Duration: (?<billed>\d+) ms\s+Memory Size: (?<mem>\d+) MB\s+Max Memory Used: (?<maxmem>\d+) MB(?:\s+Init Duration: (?<init>[\d.]+) ms)?/
| stats pct(dur, 95) as p95Ms, max(maxmem) as maxMB, count(init) as coldStarts
Init Duration は、コールドスタートのときだけ付きます。 (?:...)? で「あってもなくてもよい」にしないと、ウォームスタートの行が取り出せません。区切りがスペースかタブかに左右されないよう、\s+ を使っています。Python の re で同じ正規表現(名前付きグループは (?P<name>...) に置き換え)を当てた結果です。
| 当てた REPORT 行 | Init Duration を必須にした正規表現 |
上の正規表現(任意) |
|---|---|---|
| ドキュメントの例(スペース区切り、Init あり) | 取れた | 取れた(init: 113.51) |
| タブ区切り、Init あり | 取れた | 取れた(init: 130.49) |
| タブ区切り、Init なし(ウォーム) | 取れない(None) | 取れた(init: None) |
Init Duration: 84.00 ms Status: timeout 付き |
取れた | 取れた(dur: 3016.78) |
{'rid': '1c8df7d3-xmpl-46da-9778-518e6eca8125', 'dur': '2.75', 'billed': '3', 'mem': '128', 'maxmem': '56', 'init': None}
{'rid': '527cb862-4f5e-49a9-9ae4-a7edc90f0fda', 'dur': '3016.78', 'billed': '3101', 'mem': '128', 'maxmem': '31', 'init': '84.00'}
Status: timeout は別の parse で取り出します。
filter @type = "REPORT"
| parse @message /Status: (?<status>\w+)/
| filter ispresent(status)
| stats count(*) by status
parse に合わなかったログも結果に残り、取り出した項目だけが無い状態になります(ドキュメント)。filter ispresent(...) で合ったものだけに絞れます。
ログの形式を JSON にした関数
Lambda のログ形式を JSON にすると、REPORT 行は type が platform.report の JSON になります。Lambda のドキュメント(Telemetry API のスキーマ)にある形です。
{
"time": "2022-10-12T00:01:15.000Z",
"type": "platform.report",
"record": {
"requestId": "6d68ca91-49c9-448d-89b8-7ca3e6dc66aa",
"metrics": {"durationMs": 693.92, "billedDurationMs": 694, "memorySizeMB": 128,
"maxMemoryUsedMB": 84, "initDurationMs": 397.68},
"status": "success"
}
}
JSON のキーは入れ子を . でつないで使えるため、同じ集計は次のように書けます。
filter type = "platform.report"
| stats pct(record.metrics.durationMs, 95) as p95Ms,
max(record.metrics.maxMemoryUsedMB) as maxMB,
count(record.metrics.initDurationMs) as coldStarts
| sort p95Ms desc
record.status には success・failure・error・timeout が入ります。
API Gateway のアクセスログ
アクセスログは、ステージの設定で書式を決めます。ドキュメントの JSON の書式に、待ち時間の項目を足した例です。
{ "requestId":"$context.requestId", "ip":"$context.identity.sourceIp",
"requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod",
"resourcePath":"$context.resourcePath", "status":"$context.status",
"protocol":"$context.protocol", "responseLength":"$context.responseLength",
"responseLatency":"$context.responseLatency", "integrationLatency":"$context.integrationLatency",
"integrationStatus":"$context.integration.status", "errorMessage":"$context.error.message",
"xrayTraceId":"$context.xrayTraceId" }
| 変数(ドキュメント) | 意味 |
|---|---|
$context.responseLatency |
応答までの時間(ミリ秒) |
$context.integrationLatency |
統合(Lambda など)の時間(ミリ秒) |
$context.integration.status |
統合が返したステータス。Lambda プロキシ統合では関数が返したコード |
$context.error.message |
API Gateway のエラーメッセージ |
$context.status |
メソッドのレスポンスのステータス |
5xx の件数をパスごとに
filter status >= 500
| stats count(*) as errors by resourcePath, status
| sort errors desc
遅いパス(p95)と、API Gateway 自身の時間
stats count(*) as n,
pct(responseLatency, 95) as p95Ms,
avg(responseLatency - integrationLatency) as gatewayOverheadMs
by httpMethod, resourcePath
| sort p95Ms desc
| limit 20
responseLatency - integrationLatency は、統合の外(認証・API Gateway の処理)にかかった時間の目安です。
4xx を新しい順に(ドキュメントの例)
fields @timestamp, status, ip, path, httpMethod
| filter status>=400 and status<=499
| sort @timestamp desc
| limit 10
多いアクセス元 IP
stats count(*) as n by ip
| sort n desc
| limit 20
特定のリクエストIDのログを全部出す
Lambda のリクエストID
fields @timestamp, @message
| filter @requestId = "8f507cfc-xmpl-4697-b07a-ac58fc914c95"
| sort @timestamp asc
@requestId は Lambda のログで自動で見つかる項目です。自分で出したログの行もまとめて探すなら、filter @message like "8f507cfc-xmpl-4697-b07a-ac58fc914c95" のように文字列としても探せます。
相関IDで、複数のサービスをまたいで探す
fields @timestamp, @log, service, level, message
| filter correlation_id = "req-abc-123"
| sort @timestamp asc
複数のロググループを選んで実行すると、API Gateway → Lambda → 別の Lambda のログを時刻順に並べられます。@log で、どのロググループの行かが分かります。Powertools の Logger で相関IDを付ける方法は、関連記事「Lambda Powertools Pythonの使い方|Logger・Tracer」で扱っています。
X-Ray のトレースIDから
fields @timestamp, @message
| filter @xrayTraceId = "1-5e34a614-10bdxmplf1fb44f07bc535a1"
トレースの見方は、関連記事「AWS X-Rayの使い方|Lambda・APIのトレースとサービスマップ」で扱っています。
CLI で実行する(start-query / get-query-results)
start-query はすぐにクエリIDを返し、結果は get-query-results で取りに行きます。 時刻はエポック秒です。
LOG_GROUP=/aws/lambda/orders-api
QID=$(aws logs start-query \
--log-group-name "$LOG_GROUP" \
--start-time $(date -d '-1 hour' +%s) \
--end-time $(date +%s) \
--query-string 'fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 20' \
--query queryId --output text)
# 終わるまで待つ
while :; do
STATUS=$(aws logs get-query-results --query-id "$QID" --query status --output text)
[ "$STATUS" = "Complete" ] || [ "$STATUS" = "Failed" ] || [ "$STATUS" = "Cancelled" ] || [ "$STATUS" = "Timeout" ] && break
sleep 1
done
aws logs get-query-results --query-id "$QID" \
| jq -r '.results[] | map({(.field): .value}) | add | [.["@timestamp"], .["@message"]] | @tsv'
aws logs get-query-results --query-id "$QID" --query statistics # recordsScanned・bytesScanned など
get-query-results の結果は、1行が「field と value の組の配列」です。moto に向けて動かしたときの形です。
{
"results": [
[
{"field": "@ptr", "value": "2"},
{"field": "@timestamp", "value": "1791871068002"},
{"field": "@message", "value": "{\"level\":\"ERROR\",\"message\":\"order failed\",\"correlation_id\":\"req-1\"}"}
]
],
"status": "Complete"
}
@ptr は、そのログ1件を指す値です(aws logs get-log-record --log-record-pointer で元のログを取れます)。
status の値 |
意味 |
|---|---|
Scheduled・Running |
実行中。待って取り直す |
Complete |
終わった |
Failed・Cancelled・Timeout・Unknown |
失敗・中止・時間切れ |
Python(boto3)で実行して辞書で受け取る
"""CloudWatch Logs Insights のクエリを実行し、結果を辞書のリストで返す"""
import time
from datetime import datetime, timedelta, timezone
import boto3
logs = boto3.client("logs")
def run_query(log_groups, query, minutes=60, limit=1000, poll=1.0, timeout=300):
end = datetime.now(timezone.utc)
start = end - timedelta(minutes=minutes)
qid = logs.start_query(
logGroupNames=log_groups,
startTime=int(start.timestamp()), # 秒(エポック)
endTime=int(end.timestamp()),
queryString=query,
limit=limit,
)["queryId"]
waited = 0.0
while True:
res = logs.get_query_results(queryId=qid)
if res["status"] in ("Complete", "Failed", "Cancelled", "Timeout", "Unknown"):
break
if waited >= timeout:
logs.stop_query(queryId=qid)
raise TimeoutError(qid)
time.sleep(poll); waited += poll
if res["status"] != "Complete":
raise RuntimeError(f"query {qid}: {res['status']}")
rows = [{f["field"]: f["value"] for f in r if f["field"] != "@ptr"} for r in res["results"]]
return rows, res.get("statistics", {})
if __name__ == "__main__":
rows, stats = run_query(["/aws/lambda/orders-api"],
'filter @type = "REPORT" | stats pct(@duration, 95) as p95 by bin(1h)')
for r in rows:
print(r)
print("scanned bytes:", stats.get("bytesScanned"))
moto に向けて動かすと、{'@timestamp': '1791871068002', '@message': '{"level":"ERROR",...}'} のような辞書のリストが返りました。
moto で分かったこと(テストに使うときの注意)
| API | moto 5.2.4 の結果 |
|---|---|
start-query・get-query-results・describe-queries |
通る |
| クエリの中身 | filter が効かず、ロググループの全件が返った。stats も計算されない(@ptr だけの行になる) |
statistics |
返らない |
stop-query・put-query-definition・describe-query-definitions |
The ... action has not been implemented |
moto はクエリ言語を解釈しないため、テストで確かめられるのは「API の呼び方と結果の受け取り方」までです。クエリの正しさは、実際のロググループにコンソールで当てて確かめます。
上限(ドキュメント)
| 項目 | 値 |
|---|---|
| クエリの実行時間 | 60 分で時間切れ |
| 結果を取り出せる期間 | 7 日 |
| 同時に実行できるクエリ | Logs Insights QL は 100(ダッシュボードのクエリも含む)。PPL・SQL は 15 |
| 1回のクエリのロググループ | logGroupNames・logGroupIdentifiers で 50 まで(SOURCE では、選んだ数が 10,000 を超えるとエラー) |
返す件数(limit) |
最大 100,000。get-query-results 1回で 10,000 件まで |
| クエリ文字列 | 10,000 文字まで |
StartQuery・GetQueryResults の呼び出し |
1秒に 10 回(アカウント・リージョンごと) |
| 検索できるログ | ロググループを作る前の時刻のログは対象外 |
クエリの言語は、Logs Insights QL のほか、OpenSearch の PPL と SQL も選べます(--query-language CWLI|PPL|SQL)。
料金:スキャン量で決まる
Logs Insights の料金は、クエリが読んだ「圧縮前のログの量」で決まります。 クエリの言語は関係ありません(ドキュメント)。1 GB あたりの単価はリージョンごとに決まっていて、CloudWatch の料金ページの「ログ」に載っています。無料枠は、ログの取り込み・アーカイブ・Logs Insights のスキャンを合わせて毎月 5 GB です。
| 安く・速くする方法 | 理由 |
|---|---|
| 時間の範囲を狭くする | 読むログが減る(いちばん効く) |
| ロググループを必要なものだけ選ぶ | 同上 |
limit を付ける |
結果は減るが、スキャン量は減らないことが多い(limit any は十分な件数で早めに止める) |
フィールドインデックスと filterIndex |
値を持つロググループ・ログだけを読む |
実行前に estimate で見積もる |
スキャン量を先に見られる(ドキュメントのコマンド一覧) |
| ダッシュボードの自動更新の間隔を広げる | 更新のたびにクエリが走る |
実際に読んだ量は、get-query-results の statistics.bytesScanned で分かります。月ごとの使用量は、関連記事「AWSの料金を確認する方法|Cost Explorer・CLI・予算アラート」の方法で確かめられます。
よくある質問
Q. filter @message like "error" で何も出ません。
A. like "..." は大文字・小文字を区別します。like /(?i)error/ にすると ERROR・Error も合います。
Q. stats のあとで @timestamp が使えません。
A. stats の後は、その stats で作った項目しか使えません。時刻が要るときは stats ... by bin(5m) as t のように名前を付けて残します。
Q. CloudWatch Logs の filter-log-events との違いは何ですか。
A. filter-log-events は「パターンに合うログを取り出す」API で、集計はできません。Logs Insights は集計・並べ替え・parse ができ、料金はスキャン量で決まります。aws logs tail や filter-log-events の使い方は、関連記事「CloudWatch LogsのAWS CLI tail・検索・クエリ例」で扱っています。
Q. よく使うクエリを保存できますか。
A. コンソールの「保存」か、aws logs put-query-definition --name lambda/errors --query-string '...' --log-group-names ... で保存できます。名前に / を入れると、コンソールでフォルダーとして表示されます。
Q. 結果からアラームを作れますか。 A. 件数でアラームを付けるなら、メトリクスフィルターでログの数を CloudWatch のメトリクスにするか、EMF でメトリクスを出し、そこにアラームを付ける方法が基本です。関連記事「CloudWatchアラームをAWS CLIで作成|SNS通知・カスタム指標」で扱っています。
まとめ
- クエリは
fields | filter | stats | sort | limitをパイプでつなぐ。like "..."は大文字・小文字を区別し、/(?i).../で区別しない - Lambda は
filter @type = "REPORT"で@duration・@maxMemoryUsed・@initDurationが使える。p95 はpct(@duration, 95) parseで REPORT 行を取るときは、Init Durationを任意((?:...)?)にし、区切りは\s+にする- API Gateway はアクセスログに
responseLatency・integrationLatencyを入れると、遅いパスと API Gateway 自身の時間が分かる - 1リクエストのログは
@requestId・相関ID・@xrayTraceIdで集める - CLI は
start-query→get-query-resultsをCompleteまで繰り返す。時刻はエポック秒 - 料金はスキャンした量で決まる。時間の範囲とロググループを絞る
参考・出典
確認日はいずれも 2026年10月13日です。
- Amazon CloudWatch Logs ユーザーガイド「Analyzing log data with CloudWatch Logs Insights」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html
- Amazon CloudWatch Logs ユーザーガイド「CloudWatch Logs Insights language query syntax」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html
- Amazon CloudWatch Logs ユーザーガイド「Sample queries」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-examples.html
- Amazon CloudWatch Logs ユーザーガイド「filter」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-Filter.html
- Amazon CloudWatch Logs ユーザーガイド「stats」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-Stats.html
- Amazon CloudWatch Logs ユーザーガイド「parse」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-Parse.html
- Amazon CloudWatch Logs ユーザーガイド「Boolean, comparison, numeric, datetime, and other functions」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-operations-functions.html
- Amazon CloudWatch Logs ユーザーガイド「Supported logs and discovered fields」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_AnalyzeLogData-discoverable-fields.html
- Amazon CloudWatch Logs ユーザーガイド「CloudWatch Logs quotas」:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html
- Amazon CloudWatch Logs API リファレンス「StartQuery」:https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_StartQuery.html
- AWS Lambda 開発者ガイド「Log and monitor Python Lambda functions」:https://docs.aws.amazon.com/lambda/latest/dg/python-logging.html
- AWS Lambda 開発者ガイド「Lambda Telemetry API schema reference」:https://docs.aws.amazon.com/lambda/latest/dg/telemetry-schema-reference.html
- Amazon API Gateway 開発者ガイド「Set up CloudWatch logging for REST APIs(アクセスログ)」:https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-access-logging.html
- Amazon API Gateway 開発者ガイド「Variables for access logging」:https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-variables-for-access-logging.html
- Amazon CloudWatch の料金:https://aws.amazon.com/cloudwatch/pricing/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CloudWatch Logs Insightsのクエリ集|エラー・遅いリクエスト」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。