CloudWatch Application Signalsでトレースとログの相関を設定してみた
トレースに関連するログを簡単に確認したい
こんにちは、のんピ(@non____97)です。
皆さんはCloudWatch Application Signals(以降、Application Signals)を使用していて、トレースに関連するログを簡単に確認したいなと思ったことはありますか? 私はあります。
Application Signalsではメトリクスグラフをクリックすると、クリックした地点のスパンが最大10件表示されます。

ここで表示されたスパンのトレースIDをクリックすることでトレースの詳細を確認することが可能です。

一緒にトレースに関連するログを確認できるようになることで、ログを別途検索する手間なく、即座に詳細なエラーメッセージやスタックトレースを確認でき、調査時間を短縮できます。
実装方法は以下AWS公式ドキュメントに記載されています。
Application Signals でログ相関のトレースを有効にできます。これにより、トレース ID とスパン ID が関連するアプリケーションログに自動的に挿入されます。次に、Application Signals コンソールでトレースの詳細ページを開くと、現在のトレースに関連するログエントリがあれば、ページの下部に自動的に表示されます。
例えば、レイテンシーグラフにスパイクがあることに気付いたとします。グラフ上のそのポイントを選択すると、その時点の診断情報をロードできます。次に、関連するトレースを選択すると、詳細情報が表示されます。トレース情報を表示すると、下にスクロールしてそのトレースに関連付けられているログを参照できます。こうしたログを調べると、レイテンシーのスパイクを引き起こしている問題を突き止め、関連するパターンやエラーコードを明らかにできる可能性があります。
実際に試してみました。
いきなりまとめ
- ログ相関をするためには以下のステップを実施
- ログへのトレース情報の埋め込み
- 使用しているパッケージおよびバージョンがゼロコード計装ライブラリでサポートされているか注意しよう
- ログの出力先の指定
OTEL_RESOURCE_ATTRIBUTESのaws.log.group.namesで指定する
- ログへのトレース情報の埋め込み
- ログ相関では裏側でCloudWatch Logs Insightsが動作している
- 自動で
/ecs/から始まるロググループにもクエリしてしまう
- 自動で
やってみた
検証環境
検証環境は以下のとおりです。

ログはAWS FireLens (AWS for Fluent Bit)を使用して、エラーログはCloudWatch Logs、全てのログをData Firehose経由でS3バケットに出力させています。

以下記事のものをベースにしています。
リソースは全てAWS CDKでデプロイしています。使用しているコードは以下のとおりです。
デプロイするとOpen TelemetryやApplication Signals関連の環境変数は以下のようになります。
| キー | 値 |
|---|---|
| OTEL_AWS_APPLICATION_SIGNALS_ENABLED | false |
| OTEL_EXPORTER_OTLP_ENDPOINT | http://localhost:4318 |
| OTEL_EXPORTER_OTLP_PROTOCOL | http/protobuf |
| OTEL_LOGS_EXPORTER | none |
| OTEL_METRICS_EXPORTER | none |
| OTEL_PROPAGATORS | tracecontext,baggage,xray |
| OTEL_RESOURCE_ATTRIBUTES | service.name=ecs-express-app,deployment.environment=ecs:EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-4JfsTzadcWYq,aws.log.group.names=EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-Oieo4YPQifeI |
| OTEL_TRACES_EXPORTER | otlp |
| OTEL_TRACES_SAMPLER | xray |
| OTEL_TRACES_SAMPLER_ARG | endpoint=http://localhost:2000,polling_interval=300 |
ログへのトレース情報の埋め込み
まず、ログへのトレース情報の埋め込みを行う必要があります。
以下AWS公式ドキュメントを確認するとNode.jsについてはロガーごとのゼロコード計装ライブラリを使うように紹介されています。
Node.js
Node.js 対応のロギングライブラリを使用できるように Node.js でトレースコンテキストの挿入を有効にする方法の詳細については、Node.js での Pino、Winston、Bunyan のいずれかの自動計測に NPM を使用する方法を解説したドキュメントを参照してください。
今回はPinoを使っているので、@opentelemetry/instrumentation-pinoを使うことになります。
今回、public.ecr.aws/aws-observability/adot-autoinstrumentation-node:v0.8.1をInitコンテナで使用しているため、@opentelemetry/instrumentation-pinoを改めてインストールする必要はありません。
aws-observability/aws-otel-js-instrumentationのリリースを確認すると、以下のようにこのコンテナイメージにaws-otel-js-instrumentationが含まれていることが分かります。
See ADOT node auto-instrumentation Docker image v0.8.1 in our public ECR repository:
https://gallery.ecr.aws/aws-observability/adot-autoinstrumentation-node
そして、aws-otel-js-instrumentationのpackage-lock.jsonを確認すると、^0.46.0のPinoのゼロコード計装ライブラリが含まれていることが分かります。
注意が必要なのはPinoのバージョンです。
ゼロコード計装ライブラリのバージョンが0.46.0の場合、サポートしているPinoのバージョンは>=5.14.0 <10です。
pino versions >=5.14.0 <10
The "log sending" feature is only supported in pino v7 and later.
最新のPinoのバージョンは10.3.1です。そのため、バージョンを指定しなければゼロコード計装ライブラリがサポートしていないPinoを使用することになります。
Pinoのゼロコード計装が正常に行われている場合は以下のようにtrace_idやspan_idが付与されます。
{
"level": "error",
"time": "2026-02-11T00:42:49.466Z",
"pid": 6,
"hostname": "ip-10-10-8-112.ec2.internal",
"req": {
"id": 36,
"method": "GET",
"url": "/error/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-qzyosxmqsim4-1634003559.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.10",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.10",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-698bd089-3e85c9ad79fddc8706f7ad7f",
"cookie": "connect.sid=s%3Aa-rXSzyN-2POI_b5dkH4LkP6ijl68rve.zWuJDO786nBLrcXV3U70DxhwxfrFLqXFjPWwB9ATd%2FQ",
"user-agent": "curl/8.7.1",
"accept": "*/*"
},
"remoteAddress": "127.0.0.1",
"remotePort": 57812
},
"trace_id": "698bd089673affe7e1c8a2add24be6a9",
"span_id": "448e1d51d070a746",
"trace_flags": "01",
"res": {
"statusCode": 500,
"headers": {
"x-powered-by": "Express",
"content-type": "application/json; charset=utf-8",
"content-length": "33",
"etag": "W/\"21-Fau8GdrOCOyGNNH/IiTxy2DuMu0\""
}
},
"err": {
"type": "Error",
"message": "failed with status code 500",
"stack": "Error: failed with status code 500\n at onResFinished (/app/node_modules/.pnpm/pino-http@10.5.0/node_modules/pino-http/logger.js:115:39)\n at ServerResponse.onResponseComplete (/app/node_modules/.pnpm/pino-http@10.5.0/node_modules/pino-http/logger.js:178:14)\n at /otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:55\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_context_frame:59:14)\n at AsyncLocalStorageContextManager.with (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AsyncLocalStorageContextManager.js:33:40)\n at ServerResponse.contextWrapper (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:32)\n at ServerResponse.emit (node:events:520:35)\n at onFinish (node:_http_outgoing:1026:10)\n at callback (node:internal/streams/writable:764:21)\n at afterWrite (node:internal/streams/writable:708:5)"
},
"responseTime": 5,
"msg": "request errored",
"container_name": "app",
"source": "stderr",
"container_id": "6b8cc0c5e5f94ebe888e690dbb051168-0527074092",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/6b8cc0c5e5f94ebe888e690dbb051168",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:95"
}
一方で、Pinoのバージョンが10以上の場合は以下のようにトレース情報は記録されていません。
{
"level": "error",
"time": "2026-02-04T07:54:00.739Z",
"pid": 6,
"hostname": "ip-10-10-8-103.ec2.internal",
"req": {
"id": 63,
"method": "GET",
"url": "/error/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-fgdpbvnooxwj-1973419334.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.57",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.57",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-6982fb18-3fb552d8541fd9151d48406f",
"accept": "*/*",
"user-agent": "curl/8.7.1"
},
"remoteAddress": "127.0.0.1",
"remotePort": 53378
},
"res": {
"statusCode": 500,
"headers": {
"x-powered-by": "Express",
"content-type": "application/json; charset=utf-8",
"content-length": "33",
"etag": "W/\"21-Fau8GdrOCOyGNNH/IiTxy2DuMu0\"",
"set-cookie": [
"connect.sid=s%3An3YhhvIDKp6XWpVpDbx0U9F0GeNEHJxg.1HNNiMD4%2BhQEmjNdBO9NbQsADN67pKUccIeBYe%2Fp%2FVc; Path=/; Expires=Thu, 05 Feb 2026 07:54:00 GMT; HttpOnly"
]
}
},
"err": {
"type": "Error",
"message": "failed with status code 500",
"stack": "Error: failed with status code 500\n at onResFinished (/app/node_modules/.pnpm/pino-http@11.0.0/node_modules/pino-http/logger.js:115:39)\n at ServerResponse.onResponseComplete (/app/node_modules/.pnpm/pino-http@11.0.0/node_modules/pino-http/logger.js:178:14)\n at /otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:55\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_context_frame:59:14)\n at AsyncLocalStorageContextManager.with (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AsyncLocalStorageContextManager.js:33:40)\n at ServerResponse.contextWrapper (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:32)\n at ServerResponse.emit (node:events:520:35)\n at onFinish (node:_http_outgoing:1026:10)\n at callback (node:internal/streams/writable:764:21)\n at afterWrite (node:internal/streams/writable:708:5)"
},
"responseTime": 3,
"msg": "request errored",
"container_name": "app",
"source": "stderr",
"container_id": "0dfd495fff0048de92bd87f68daa8de1-0527074092",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-s5tytpIiJ9VQ",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-s5tytpIiJ9VQ/0dfd495fff0048de92bd87f68daa8de1",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:93"
}
同様にExpressなど他パッケージもゼロコード計装をサポートしているバージョンか気をつけましょう。ドキュメントはもちろん、以下のようにソースコードの中にサポートバージョンが記載されています。
ログ出力先の指定
トレースとログの相関を行うためにログ出力先の指定をします。
具体的にはOTEL_RESOURCE_ATTRIBUTESにaws.log.group.names=<出力先のロググループ名>を指定する形です。
(オプション) Application Signals のログ相関を有効にするには、追加で環境変数 aws.log.group.names にアプリケーションログのロググループ名を設定します。これにより、アプリケーションが生成したトレースとメトリクスをこのロググループ内の該当するログエントリと関連付けることができます。この変数では、$YOUR_APPLICATION_LOG_GROUP をアプリケーションのロググループ名に置き換えます。複数のロググループがある場合は、アンパサンド (&) を使用して、次の例のようにそれらを分離できます: aws.log.group.names=log-group-1&log-group-2。ログ相関のメトリクスを有効にするには、この現在の環境変数を設定するだけで十分です。詳細については、「ログ相関のメトリクスを有効にする」を参照してください。ログ相関のトレースを有効にするには、アプリケーションのログ記録設定も変更する必要があります。詳細については、「ログ相関のトレースを有効にする」を参照してください。
こうすると、スパンのawsのプロパティのcloudwatch_logsに指定したロググループ名が記載されます。
{
"ecs.task.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/015048a8181a46e4bbc15539e33568f7",
"ecs.task.family": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2",
"ecs.cluster.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:cluster/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs": {
"container": "ip-10-10-8-74.ec2.internal",
"container_id": "46e4bbc15539e33568f7/015048a8181a46e4bbc15539e33568f7-0527074092"
},
"ecs.container.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:container/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/015048a8181a46e4bbc15539e33568f7/8059f724-8aeb-4554-afd9-bddf9f15b80e",
"ecs.launchtype": "fargate",
"span.kind": "CLIENT",
"cloudwatch_logs": [
{
"log_group": "EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9"
}
],
"ecs.task.revision": "100"
},
なお、Open Telemetry Collectorでトレースのパイプラインに以下のようにECSのDetectorsを含めるresourcedetectionを挟むとログ相関を行うことができません。
processors:
.
.
(中略)
.
.
resourcedetection:
detectors: [env, ecs]
timeout: 5s
override: false
.
.
(中略)
.
.
service:
extensions: [sigv4auth, awsproxy]
pipelines:
traces:
receivers: [otlp]
processors: [filter/exclude_health, resourcedetection, batch]
exporters: [otlphttp]
具体的には以下のようにデータの取得中にエラーが発生しましたと表示されてしまいます。

※ CloudWatch > Transaction SearchからもCloudWatch > トレースからも同様の結果です
後述するとおりログ相関の裏側ではCloudWatch Logs Insightsが実行されるのですが、このときはLogs Insightsが実行された形跡もありませんでした。
ちなみに、このときのスパンのawsのプロパティに以下のようにcloudwatch_logsやlog.stream.arns、log.stream.namesにログドライバーawslogsのコンテナのログ出力先のロググループおよびログストリームが記録されていました。
{
"ecs.task.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/2a9e9b028b6b4bd0b4edf85023bd9c3b",
"ecs.task.family": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2",
"ecs.cluster.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:cluster/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs": {
"container": "ip-10-10-8-125.ec2.internal",
"container_id": "4bd0b4edf85023bd9c3b/2a9e9b028b6b4bd0b4edf85023bd9c3b-0527074092"
},
"ecs.container.arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:container/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/2a9e9b028b6b4bd0b4edf85023bd9c3b/e8984edf-97c0-4e46-a8ea-23018b9537c6",
"ecs.launchtype": "fargate",
"span.kind": "CLIENT",
"cloudwatch_logs": [
{
"log_group": "EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9"
},
{
"log_group": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-EcsConstructTaskDefinitionAdotAutoInstrumentationInitContainerLogGroup8060A51D-TTDVP1HlaLC8"
},
{
"log_group": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-EcsConstructTaskDefinitionlogRouterLogGroup27EC9B3C-OxmB1VpOf8SS"
}
],
"ecs.task.revision": "100",
"log.stream.arns": [
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-EcsConstructTaskDefinitionAdotAutoInstrumentationInitContainerLogGroup8060A51D-TTDVP1HlaLC8:log-stream:init/init/2a9e9b028b6b4bd0b4edf85023bd9c3b",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-EcsConstructTaskDefinitionlogRouterLogGroup27EC9B3C-OxmB1VpOf8SS:log-stream:firelens/EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2/logRouter/2a9e9b028b6b4bd0b4edf85023bd9c3b"
],
"log.stream.names": [
"init/init/2a9e9b028b6b4bd0b4edf85023bd9c3b",
"firelens/EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2/logRouter/2a9e9b028b6b4bd0b4edf85023bd9c3b"
],
"ecs.task.id": "2a9e9b028b6b4bd0b4edf85023bd9c3b"
},
他はecs.task.idが増える程度なのでパイプラインに挟まないようにしましょう。
動作確認
動作確認をします。
Application Signalsのサービスからメトリクスのグラフのデータポイントをクリックし、相関スパンを表示します。

相関スパン内のトレースIDをクリックします。
すると、以下のようにトレースに関連づくログも一緒に確認できました。

{
"level": "error",
"time": "2026-02-11T05:39:13.085Z",
"pid": 8,
"hostname": "ip-10-10-8-89.ec2.internal",
"req": {
"id": 479,
"method": "GET",
"url": "/crash/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-qzyosxmqsim4-1634003559.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.40",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.40",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-698c1601-5ec60d115f6377e539ba7666",
"cookie": "connect.sid=s%3AkdwCTdPnOMbapxgvwkYpR3T2Y1Ykw_eW.cef%2Bw5X7jVYHTqDmz0m8XtFUePmZOE225Vy9JSE%2B4uQ",
"user-agent": "curl/8.7.1",
"accept": "*/*"
},
"remoteAddress": "127.0.0.1",
"remotePort": 33256
},
"trace_id": "698c160176b2820f3142596543b58e08",
"span_id": "84537a0cf5432a39",
"trace_flags": "01",
"msg": "Crash endpoint triggered - throwing exception",
"container_id": "26510d3c39984a7cb58a1bf43dda452b-0527074092",
"container_name": "app",
"source": "stderr",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/26510d3c39984a7cb58a1bf43dda452b",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:98"
}
{
"level": "error",
"time": "2026-02-11T05:39:13.086Z",
"pid": 8,
"hostname": "ip-10-10-8-89.ec2.internal",
"req": {
"id": 479,
"method": "GET",
"url": "/crash/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-qzyosxmqsim4-1634003559.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.40",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.40",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-698c1601-5ec60d115f6377e539ba7666",
"cookie": "connect.sid=s%3AkdwCTdPnOMbapxgvwkYpR3T2Y1Ykw_eW.cef%2Bw5X7jVYHTqDmz0m8XtFUePmZOE225Vy9JSE%2B4uQ",
"user-agent": "curl/8.7.1",
"accept": "*/*"
},
"remoteAddress": "127.0.0.1",
"remotePort": 33256
},
"trace_id": "698c160176b2820f3142596543b58e08",
"span_id": "84537a0cf5432a39",
"trace_flags": "01",
"err": {
"type": "Error",
"message": "Application crash test - intentional exception",
"stack": "Error: Application crash test - intentional exception\n at /app/dist/router.js:218:11\n at Layer.handle [as handle_request] (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/layer.js:95:5)\n at next (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/route.js:149:13)\n at Route.dispatch (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/route.js:119:3)\n at patched (/otel-auto-instrumentation/node_modules/@opentelemetry/instrumentation-express/build/src/instrumentation.js:210:37)\n at Layer.handle [as handle_request] (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/layer.js:95:5)\n at /app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/index.js:284:15\n at router.process_params (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/index.js:346:12)\n at next (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/index.js:280:10)\n at router.handle (/app/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/router/index.js:175:3)"
},
"msg": "Error occurred",
"container_id": "26510d3c39984a7cb58a1bf43dda452b-0527074092",
"container_name": "app",
"source": "stderr",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/26510d3c39984a7cb58a1bf43dda452b",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:98"
}
{
"level": "error",
"time": "2026-02-11T05:39:13.088Z",
"pid": 8,
"hostname": "ip-10-10-8-89.ec2.internal",
"req": {
"id": 479,
"method": "GET",
"url": "/crash/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-qzyosxmqsim4-1634003559.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.40",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.40",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-698c1601-5ec60d115f6377e539ba7666",
"cookie": "connect.sid=s%3AkdwCTdPnOMbapxgvwkYpR3T2Y1Ykw_eW.cef%2Bw5X7jVYHTqDmz0m8XtFUePmZOE225Vy9JSE%2B4uQ",
"user-agent": "curl/8.7.1",
"accept": "*/*"
},
"remoteAddress": "127.0.0.1",
"remotePort": 33256
},
"trace_id": "698c160176b2820f3142596543b58e08",
"span_id": "84537a0cf5432a39",
"trace_flags": "01",
"res": {
"statusCode": 500,
"headers": {
"x-powered-by": "Express",
"content-type": "application/json; charset=utf-8",
"content-length": "33",
"etag": "W/\"21-Fau8GdrOCOyGNNH/IiTxy2DuMu0\""
}
},
"err": {
"type": "Error",
"message": "failed with status code 500",
"stack": "Error: failed with status code 500\n at onResFinished (/app/node_modules/.pnpm/pino-http@10.5.0/node_modules/pino-http/logger.js:115:39)\n at ServerResponse.onResponseComplete (/app/node_modules/.pnpm/pino-http@10.5.0/node_modules/pino-http/logger.js:178:14)\n at /otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:55\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_context_frame:59:14)\n at AsyncLocalStorageContextManager.with (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AsyncLocalStorageContextManager.js:33:40)\n at ServerResponse.contextWrapper (/otel-auto-instrumentation/node_modules/@opentelemetry/context-async-hooks/build/src/AbstractAsyncHooksContextManager.js:50:32)\n at ServerResponse.emit (node:events:520:35)\n at onFinish (node:_http_outgoing:1026:10)\n at callback (node:internal/streams/writable:764:21)\n at afterWrite (node:internal/streams/writable:708:5)"
},
"responseTime": 5,
"msg": "request errored",
"container_id": "26510d3c39984a7cb58a1bf43dda452b-0527074092",
"container_name": "app",
"source": "stderr",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-zJnVnD9x7R6g/26510d3c39984a7cb58a1bf43dda452b",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:98"
}
依存関係の可用性が低くなっている場合も確認できます。



このときのログは以下のとおりです。
{
"level": "error",
"time": "2026-02-12T09:08:27.268Z",
"pid": 7,
"hostname": "ip-10-10-8-82.ec2.internal",
"req": {
"id": 15,
"method": "GET",
"url": "/health",
"query": {},
"params": {},
"headers": {
"host": "localhost:3000",
"user-agent": "Wget",
"accept": "*/*",
"connection": "close"
},
"remoteAddress": "127.0.0.1",
"remotePort": 57732
},
"trace_id": "698d988b0f2d820050ca5552c933f32d",
"span_id": "f9ff425ef6931901",
"trace_flags": "01",
"err": {
"type": "ReplyError",
"message": "ERR syntax error",
"stack": "ReplyError: ERR syntax error\n at parseError (/app/node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/lib/parser.js:179:12)\n at parseType (/app/node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/lib/parser.js:302:14)",
"command": {
"name": "set",
"args": [
"sess:st2zrsEzLyFlzb5i4XocReBSUhmyjgRz",
"{\"cookie\":{\"originalMaxAge\":86400000,\"expires\":\"2026-02-13T09:08:27.265Z\",\"secure\":false,\"httpOnly\":true,\"path\":\"/\"}}",
"[object Object]"
]
}
},
"msg": "Error occurred",
"container_id": "3d5c2659c6ad4d0587a43191759bd918-0527074092",
"container_name": "app",
"source": "stderr",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-4JfsTzadcWYq",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-4JfsTzadcWYq/3d5c2659c6ad4d0587a43191759bd918",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:103"
}
トレースIDをクリックして、トレース詳細を確認するタイミングでLogs Insightsの実行履歴を確認すると以下クエリが実行されていました。

fields @message, @log, traceId, spanId | filter traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
fields @message, @log, traceId, spanId, jsonparse(@message) as json_message | unnest json_message.links into link | filter link.traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
fields @message, @log, traceId, spanId | filter traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
fields @message, @log, traceId, spanId, jsonparse(@message) as json_message | unnest json_message.links into link | filter link.traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
fields @log, @timestamp, @message
| filter @message like "698c160176b2820f3142596543b58e08" or @message like "8c1601762820f3142596543b58e08"
| sort @timestamp, @message desc
fields @log, @timestamp, @message
| filter @message like "698c160176b2820f3142596543b58e08" or @message like "8c1601762820f3142596543b58e08"
| sort @timestamp, @message desc
要するに3種類のクエリがそれぞれ2回ずつ実行されています。
クエリ対象のロググループ名から考えるにログ相関をしているのは上述の後ろ2つのものでしょう。
このときのCloudTrailのイベントは以下のとおりです。
{
"eventVersion": "1.11",
"userIdentity": {
"type": "AssumedRole",
"principalId": "<プリンシパルID>",
"arn": "arn:aws:sts::<AWSアカウントID>:assumed-role/<IAMロール名>/<セッション名>",
"accountId": "<AWSアカウントID>",
"accessKeyId": "<アクセスキー>",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "<プリンシパルID>",
"arn": "arn:aws:iam::<AWSアカウントID>:role/<IAMロール名>",
"accountId": "<AWSアカウントID>",
"userName": "<IAMユーザー名>"
},
"attributes": {
"creationDate": "2026-02-11T05:38:53Z",
"mfaAuthenticated": "true"
}
}
},
"eventTime": "2026-02-11T05:45:59Z",
"eventSource": "logs.amazonaws.com",
"eventName": "StartQuery",
"awsRegion": "us-east-1",
"sourceIPAddress": "<送信元IPアドレス>",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
"requestParameters": {
"logGroupNames": [
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/default-nginx-5d29",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-firelens-sidecar-container",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-otel-sidecar-collector",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/nginx",
"arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9"
],
"startTime": 1770788338,
"endTime": 1770788383,
"queryString": "fields @log, @timestamp, @message\n| filter @message like \"698c160176b2820f3142596543b58e08\" or @message like \"8c1601762820f3142596543b58e08\"\n| sort @timestamp, @message desc",
"dryRun": false
},
"responseElements": null,
"additionalEventData": {
"queryId": "5f79c759-30fa-45e5-adff-e68542d98ab0"
},
"requestID": "3f4c9697-9f6f-4213-891d-3f72959a2916",
"eventID": "cc9165a8-ecda-4992-9498-dbe332ebce96",
"readOnly": true,
"resources": [
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/default-nginx-5d29"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-firelens-sidecar-container"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-otel-sidecar-collector"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/nginx"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9"
}
],
"eventType": "AwsApiCall",
"apiVersion": "20140328",
"managementEvent": true,
"recipientAccountId": "<AWSアカウントID>",
"eventCategory": "Management",
"tlsDetails": {
"tlsVersion": "TLSv1.3",
"cipherSuite": "TLS_AES_128_GCM_SHA256",
"clientProvidedHostHeader": "logs.us-east-1.amazonaws.com"
},
"sessionCredentialFromConsole": "true"
}
"startTime": 1770788338、"endTime": 1770788383であることから指定されたロググループ内の45秒間で該当するログを探してきていることが分かります。
気になるのは/ecs/や/ecs/default-nginx-5d29など/ecs/から始まるロググループもクエリ対象としていることです。このような条件は指定していません。
CloudTrailを確認にすると、ログ相関を行うタイミングで/ecs/から始まるロググループを探していました。
{
"eventVersion": "1.11",
"userIdentity": {
"type": "AssumedRole",
"principalId": "<プリンシパルID>",
"arn": "arn:aws:sts::<AWSアカウントID>:assumed-role/<IAMロール名>/<セッション名>",
"accountId": "<AWSアカウントID>",
"accessKeyId": "<アクセスキー>",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "<プリンシパルID>",
"arn": "arn:aws:iam::<AWSアカウントID>:role/<IAMロール名>",
"accountId": "<AWSアカウントID>",
"userName": "<IAMユーザー名>"
},
"attributes": {
"creationDate": "2026-02-11T05:38:53Z",
"mfaAuthenticated": "true"
}
}
},
"eventTime": "2026-02-11T06:02:54Z",
"eventSource": "logs.amazonaws.com",
"eventName": "DescribeLogGroups",
"awsRegion": "us-east-1",
"sourceIPAddress": "<送信元IPアドレス>",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
"requestParameters": {
"logGroupNamePrefix": "/ecs/",
"includeLinkedAccounts": true
},
"responseElements": null,
"requestID": "c59cb761-d8cf-4c71-aa7e-24e7ca4a9cb7",
"eventID": "46c30084-8d1d-4484-a167-0b4821b413fc",
"readOnly": true,
"resources": [
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/default-nginx-5d29"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-firelens-sidecar-container"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/ecs-aws-otel-sidecar-collector"
},
{
"accountId": "<AWSアカウントID>",
"type": "AWS::Logs::LogGroup",
"ARN": "arn:aws:logs:us-east-1:<AWSアカウントID>:log-group:/ecs/nginx"
}
],
"eventType": "AwsApiCall",
"apiVersion": "20140328",
"managementEvent": true,
"recipientAccountId": "<AWSアカウントID>",
"eventCategory": "Management",
"tlsDetails": {
"tlsVersion": "TLSv1.3",
"cipherSuite": "TLS_AES_128_GCM_SHA256",
"clientProvidedHostHeader": "logs.us-east-1.amazonaws.com"
},
"sessionCredentialFromConsole": "true"
}
個人的にはこの機能は無効化したいですね。
/ecs/から始まるロググループで大量のログが流れている場合にLogs Insightsの課金が気になります。filter @message like "<トレースID>"とログメッセージ本文全体に対してlikeで検索しているため、フィールドインデックスも効きません。
/ecs/から始まるロググループをログ相関の対象に含める機能をオプトアウトする方法をご存知の方いれば教えて欲しいです。
個人的には回避するために/ecs/から始まるロググループを作成しない方向に持っていこうかなと考えています。
ログ相関は簡単に設定できる
CloudWatch Application Signalsでトレースとログの相関をしてみました。
サポートされているロガーを使用して、ロググループ名を環境変数で指定するだけなので思ったより簡単でした。
ちなみに今回CloudWatch Logsに流しているログはエラーログのみなので、HTTPステータスコード200が返る際にはログ相関はできません。
ログは全てData Firehose経由でS3バケットに出力しています。HTTPステータスコード200のログを探す場合はトレースIDを使って検索しましょう。以下のようなログが記録されています。
{
"level": "info",
"time": "2026-02-12T01:48:36.868Z",
"pid": 7,
"hostname": "ip-10-10-8-104.ec2.internal",
"req": {
"id": 55,
"method": "GET",
"url": "/",
"query": {},
"params": {},
"headers": {
"host": "ecsnat-albco-shaasnih0xar-1652870936.us-east-1.elb.amazonaws.com",
"x-real-ip": "10.10.8.43",
"x-forwarded-for": "<送信元IPアドレス>, 10.10.8.43",
"x-forwarded-proto": "http",
"connection": "close",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-698d3174-5876cff8075b183978fe1d65",
"accept": "*/*",
"user-agent": "curl/8.7.1"
},
"remoteAddress": "127.0.0.1",
"remotePort": 35448
},
"trace_id": "698d3174fa6d5a5d85e08988b96c738d",
"span_id": "6f704133bb94ada4",
"trace_flags": "01",
"res": {
"statusCode": 200,
"headers": {
"x-powered-by": "Express",
"content-type": "application/json; charset=utf-8",
"content-length": "427",
"etag": "W/\"1ab-kBv3WE96jXCcAIdDtz3e81LLMik\"",
"set-cookie": [
"connect.sid=s%3A_ykD64hKoji4n7SB71zDtgljHN5UDJBx.7y5uIGbxZsGgM4knIOw1Pt7BAOhIo%2FA6NLGKotG6hoU; Path=/; Expires=Fri, 13 Feb 2026 01:48:36 GMT; HttpOnly"
]
}
},
"responseTime": 292,
"msg": "request completed",
"container_id": "c9979e7d4b08471b8285c6b3ecfd5cfb-0527074092",
"container_name": "app",
"source": "stdout",
"ecs_cluster": "EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-VoUD00RfbaSW",
"ecs_task_arn": "arn:aws:ecs:us-east-1:<AWSアカウントID>:task/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-VoUD00RfbaSW/c9979e7d4b08471b8285c6b3ecfd5cfb",
"ecs_task_definition": "EcsNativeBlueGreenStackEcsConstructTaskDefinitionF683F4B2:102",
"datetime": "2026-02-12T01:48:36.869Z"
}
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!






