CloudWatch Application Signalsでトレースとログの相関を設定してみた

CloudWatch Application Signalsでトレースとログの相関を設定してみた

ログ相関は簡単に設定できる
2026.02.12

トレースに関連するログを簡単に確認したい

こんにちは、のんピ(@non____97)です。

皆さんはCloudWatch Application Signals(以降、Application Signals)を使用していて、トレースに関連するログを簡単に確認したいなと思ったことはありますか? 私はあります。

Application Signalsではメトリクスグラフをクリックすると、クリックした地点のスパンが最大10件表示されます。

8.相関するスパン.png

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

12.障害のトレース.png

一緒にトレースに関連するログを確認できるようになることで、ログを別途検索する手間なく、即座に詳細なエラーメッセージやスタックトレースを確認でき、調査時間を短縮できます。

実装方法は以下AWS公式ドキュメントに記載されています。

Application Signals でログ相関のトレースを有効にできます。これにより、トレース ID とスパン ID が関連するアプリケーションログに自動的に挿入されます。次に、Application Signals コンソールでトレースの詳細ページを開くと、現在のトレースに関連するログエントリがあれば、ページの下部に自動的に表示されます。

例えば、レイテンシーグラフにスパイクがあることに気付いたとします。グラフ上のそのポイントを選択すると、その時点の診断情報をロードできます。次に、関連するトレースを選択すると、詳細情報が表示されます。トレース情報を表示すると、下にスクロールしてそのトレースに関連付けられているログを参照できます。こうしたログを調べると、レイテンシーのスパイクを引き起こしている問題を突き止め、関連するパターンやエラーコードを明らかにできる可能性があります。

ログ相関のトレースを有効にする - Amazon CloudWatch

実際に試してみました。

いきなりまとめ

  • ログ相関をするためには以下のステップを実施
    • ログへのトレース情報の埋め込み
      • 使用しているパッケージおよびバージョンがゼロコード計装ライブラリでサポートされているか注意しよう
    • ログの出力先の指定
      • OTEL_RESOURCE_ATTRIBUTESaws.log.group.namesで指定する
  • ログ相関では裏側でCloudWatch Logs Insightsが動作している
    • 自動で/ecs/から始まるロググループにもクエリしてしまう

やってみた

検証環境

検証環境は以下のとおりです。

AWS Distro for OpenTelemetry (ADOT) Collector と ADOT SDKをとでCloudWatch Application Signalsを使ってみた.png

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

テレメトリ.png

以下記事のものをベースにしています。

https://dev.classmethod.jp/articles/cloudwatch-application-signals-with-adot-collector-and-sdk/

リソースは全てAWS CDKでデプロイしています。使用しているコードは以下のとおりです。

https://github.com/non-97/ecs-native-blue-green/tree/v2.0.2

デプロイすると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 を使用する方法を解説したドキュメントを参照してください。

ログ相関のトレースを有効にする - Amazon CloudWatch

今回は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

Releases · aws-observability/aws-otel-js-instrumentation

そして、aws-otel-js-instrumentationpackage-lock.jsonを確認すると、^0.46.0のPinoのゼロコード計装ライブラリが含まれていることが分かります。

https://github.com/aws-observability/aws-otel-js-instrumentation/blob/v0.8.1/package-lock.json#L4269

注意が必要なのは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.

@opentelemetry/instrumentation-pino - npm

最新のPinoのバージョンは10.3.1です。そのため、バージョンを指定しなければゼロコード計装ライブラリがサポートしていないPinoを使用することになります。

Pinoのゼロコード計装が正常に行われている場合は以下のようにtrace_idspan_idが付与されます。

Pinoのゼロコード計装が正常に行われている場合
{
    "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以上の場合は以下のようにトレース情報は記録されていません。

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など他パッケージもゼロコード計装をサポートしているバージョンか気をつけましょう。ドキュメントはもちろん、以下のようにソースコードの中にサポートバージョンが記載されています。

https://github.com/open-telemetry/opentelemetry-js-contrib/blob/12adb4354f09ade438cd96340bdfd1f715b5fed3/plugins/node/opentelemetry-instrumentation-express/src/instrumentation.ts#L53-L62

ログ出力先の指定

トレースとログの相関を行うためにログ出力先の指定をします。

具体的にはOTEL_RESOURCE_ATTRIBUTESaws.log.group.names=<出力先のロググループ名>を指定する形です。

(オプション) Application Signals のログ相関を有効にするには、追加で環境変数 aws.log.group.names にアプリケーションログのロググループ名を設定します。これにより、アプリケーションが生成したトレースとメトリクスをこのロググループ内の該当するログエントリと関連付けることができます。この変数では、$YOUR_APPLICATION_LOG_GROUP をアプリケーションのロググループ名に置き換えます。複数のロググループがある場合は、アンパサンド (&) を使用して、次の例のようにそれらを分離できます: aws.log.group.names=log-group-1&log-group-2。ログ相関のメトリクスを有効にするには、この現在の環境変数を設定するだけで十分です。詳細については、「ログ相関のメトリクスを有効にする」を参照してください。ログ相関のトレースを有効にするには、アプリケーションのログ記録設定も変更する必要があります。詳細については、「ログ相関のトレースを有効にする」を参照してください。

サイドカー戦略を使用してデプロイする - Amazon CloudWatch

こうすると、スパンの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]

具体的には以下のようにデータの取得中にエラーが発生しましたと表示されてしまいます。

1.データの取得中にエラーが発生しました.png

CloudWatch > Transaction SearchからもCloudWatch > トレースからも同様の結果です

後述するとおりログ相関の裏側ではCloudWatch Logs Insightsが実行されるのですが、このときはLogs Insightsが実行された形跡もありませんでした。

ちなみに、このときのスパンのawsのプロパティに以下のようにcloudwatch_logslog.stream.arnslog.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のサービスからメトリクスのグラフのデータポイントをクリックし、相関スパンを表示します。

4.相関スパン.png

相関スパン内のトレースIDをクリックします。

すると、以下のようにトレースに関連づくログも一緒に確認できました。

10.ログ相関の確認.png

{
    "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"
}

依存関係の可用性が低くなっている場合も確認できます。

12.Rediの依存関係.png
13.Redis相関スパン.png
11.Redis接続失敗時のトレース.png

このときのログは以下のとおりです。

{
    "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の実行履歴を確認すると以下クエリが実行されていました。

5.リロード後.png

aws/spans
fields @message, @log, traceId, spanId | filter traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
aws/spans
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
aws/spans
fields @message, @log, traceId, spanId | filter traceId = "698c160176b2820f3142596543b58e08" | sort @timestamp desc | limit 10000
aws/spans
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
/ecs/,/ecs/default-nginx-5d29,/ecs/ecs-aws-firelens-sidecar-container,/ecs/ecs-aws-otel-sidecar-collector,/ecs/nginx,EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9
fields @log, @timestamp, @message
| filter @message like "698c160176b2820f3142596543b58e08" or @message like "8c1601762820f3142596543b58e08"
| sort @timestamp, @message desc
/ecs/,/ecs/default-nginx-5d29,/ecs/ecs-aws-firelens-sidecar-container,/ecs/ecs-aws-otel-sidecar-collector,/ecs/nginx,EcsNativeBlueGreenStack-FirelensConstructFirelensLogGroupD186C82F-wTQ4890Mp8e9
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を使って検索しましょう。以下のようなログが記録されています。

s3://ecsnativebluegreenstack-firelensconstructfirelensl-xwd5tetsrypf/ecs/EcsNativeBlueGreenStack-EcsConstructCluster14AE103B-VoUD00RfbaSW/app/stdout/2026/02/12/01/EcsNativeBlueGreenStack-FirelensConstructDeliverySt-TCVIns4InZMR-1-2026-02-12-01-48-38-aabb7cef-5384-33e4-937c-40c34494cb1c.gz
{
  "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)でした!

この記事をシェアする

FacebookHatena blogX

関連記事