Application Signalsは、CloudWatchに組み込まれたAWSのAPM(アプリケーション性能監視)機能です。AWS Distro for OpenTelemetry(ADOT)の自動計装でアプリケーションのリクエストを拾い、サービスごとのレイテンシー・障害・エラーとサービス間の依存関係をCloudWatchに表示します。コードを書き換える必要はありませんが、どこまで自動でやってくれるかは実行基盤で大きく違います。EKSならアドオン1つでほぼ終わる一方、ECSとEC2ではCloudWatchエージェントとADOTを自分で組み込み、サービス名も自分で指定します。
この記事では、ECS・EKS・EC2・Lambdaそれぞれの有効化手順を、タスク定義・Pod注釈・エージェント設定の実際の記述で示し、最後にデータが表示されないときの確認順をまとめます。設定値はAWS公式ドキュメント「Enable your applications on Amazon ECS」ほか各プラットフォームの有効化ページ(2026年10月時点)に基づきます。料金の試算とSLOの設計はCloudWatch Application Signalsの料金・SLO設計の解説で扱っています。
まとめ|Application Signalsを有効化するための要点
- ECS・EKS・EC2・Kubernetesでは、アカウントでの初回有効化(サービスリンクロールの作成)、CloudWatchエージェントの
application_signals設定、ADOTによる計装の3段階が要る。Lambdaはエージェントを使わず、レイヤーが計装を担う。 - EKSはCloudWatch Observabilityアドオンを入れて、Podか名前空間に注釈を付ければ計装まで終わる。v5.0.0以降のアドオンは既定で自動監視が有効になるため、既存のOpenTelemetry計装があるクラスターでは先に設定を確認する。
- ECSはサイドカー方式かデーモン方式を選ぶ。Fargateならサイドカー方式しか選べない。サービス名は
OTEL_RESOURCE_ATTRIBUTESのservice.nameで自分で付け、付け忘れるとUnknownServiceと表示される。 - EC2とオンプレミスは、2023年11月30日以降に公開されたCloudWatchエージェントとADOTエージェントを手で入れる。オンプレミスはIAMユーザーのアクセスキーで認証する。
- Lambdaはコンソールのチェックボックス1つで有効化できる。データが出ないときは、最後の変更から15分待ってから、検出の有効化・エージェントの稼働・権限・計装の順に確認する。
Application Signalsの導入に共通する3段階と基盤ごとの違い
ECS・EKS・EC2・Kubernetesでは、手順の見た目は違っても中身は次の3段階に分かれます。EKSのアドオンは、このうち2と3をまとめて肩代わりしているだけです。Lambdaは例外で、1のあとはCloudWatchエージェントを置かず、ADOTを含むLambdaレイヤーが計装と送信を担います。
- アカウントでの初回有効化:リージョンごとに1回。サービスリンクロール
AWSServiceRoleForCloudWatchApplicationSignalsが作られ、X-Rayのサービスグラフ、CloudWatch Logsのクエリ、CloudWatchメトリクスの読み取りなどの権限がApplication Signalsに渡る。 - CloudWatchエージェントの設定:アプリケーションからOTLPでメトリクスとトレースを受ける窓口。ポート4316で受け、2000番はX-Rayのサンプリング設定の取得に使う。
- ADOTによる計装:言語ごとのADOTエージェントをアプリケーションに読み込ませ、環境変数で送信先とサービス名を指定する。
1はコンソールの「Application Signals」→「サービス」→「サービスの検出を開始」でも実行できますが、CLIなら次の1行です。CloudFormationではAWS::ApplicationSignals::Discoveryリソースが同じ役割を持ちます。
aws application-signals start-discovery --region ap-northeast-1
2のエージェント設定は、ECS・EC2・Kubernetesのいずれでも次のJSONが最小構成です。tracesとlogsの両方にapplication_signalsを書くのがポイントで、片方だけだとトレースかメトリクスのどちらかが欠けます。
{
"traces": {
"traces_collected": {
"application_signals": {}
}
},
"logs": {
"metrics_collected": {
"application_signals": {}
}
}
}
基盤ごとの違いは次の表のとおりです。サービス名を自動で拾ってくれるのはEKS(アドオン経由)とLambdaだけで、ECS・EC2・EKS以外のKubernetesはカスタムセットアップ扱いになり、指定した名前がそのままダッシュボードに出ます。
| 基盤 | エージェントの置き方 | 計装の入れ方 | サービス名 |
|---|---|---|---|
| EKS | アドオンがDaemonSetで配置 | Pod・名前空間の注釈 | 自動 |
| ECS(Fargate) | タスクごとのサイドカー | initコンテナ+環境変数 | 手動指定 |
| ECS(EC2起動タイプ) | サイドカーかデーモン | initコンテナ+環境変数 | 手動指定 |
| EC2・オンプレミス | ホストにインストール | 起動コマンド+環境変数 | 手動指定 |
| EKS以外のKubernetes | Helmチャート | Pod・名前空間の注釈 | 手動指定 |
| Lambda | 不要 | Lambdaレイヤー | 関数名 |
計装できる言語は、AWSのサポート表でJava(JVM 8・11・17・21・23・25)、Python(3.10〜3.14)、Node.js(18・20・22・24)、.NET(8・9・10と.NET Framework 4.6.2以降)です。Go・PHP・RubyはADOTの自動計装が無く、標準のOpenTelemetry SDKで送る構成になります。この場合の課金上の注意はApplication Signalsの料金・対応言語の解説を参照してください。
ECSでの有効化|サイドカー方式とデーモン方式
ECSでは、CloudWatchエージェントをどこで動かすかで2つの方式があります。どちらもADOTの計装はアプリケーションのタスク定義側に書くので、違うのはエージェントの置き場所と、アプリケーションから見た送信先アドレスです。
サイドカーとデーモンを分ける判断基準
| 観点 | サイドカー方式 | デーモン方式 |
|---|---|---|
| Fargate | 対応 | 非対応 |
| EC2起動タイプ | 対応 | 対応 |
| ネットワークモード | awsvpcのみ | host・bridge・awsvpc |
| エージェントの設定回数 | タスク定義ごと | クラスターで1回 |
| 送信先アドレス | 常にlocalhost | hostモード以外はインスタンスのIP |
Fargateならサイドカー方式一択です。EC2起動タイプでも、awsvpcのタスクならサイドカー方式を勧めます。bridgeのタスクはサイドカー方式に対応していないため、awsvpcへ移すか、デーモン方式を選ぶかのどちらかになります。デーモン方式はエージェントが1か所で済む代わりに、bridgeとawsvpcではアプリケーションの環境変数にコンテナインスタンスのプライベートIPを書く必要があり、インスタンスが入れ替わるたびに値が変わる問題を自分で解決しなければなりません。デーモン方式が素直に使えるのは、アプリケーションもhostネットワークモードで動かしている場合です。
サイドカー方式のタスク定義(Javaの例)
まず、エージェント設定のJSONをSSMパラメータストアに置きます。タスク定義からはsecretsのvalueFromで読み込むため、タスク実行ロールにパラメータの読み取り権限(ssm:GetParameters)が必要です。タスクロールには、アプリケーション自身の権限に加えてCloudWatchAgentServerPolicyを付けます。
aws ssm put-parameter \
--name "ecs-cwagent" \
--type "String" \
--value "`cat /tmp/ecs-cwagent.json`" \
--region ap-northeast-1
タスク定義には、共有ボリューム、エージェントのサイドカー、ADOTのjarをコピーするinitコンテナ、アプリケーションの環境変数の4つを足します。公式手順をJavaアプリケーション1つの形にまとめると次のとおりです。イメージのタグは、ECR Publicのcloudwatch-agentとadot-autoinstrumentation-javaで最新を確認して固定してください(2026年10月2日時点のGitHubリリースはADOT Java v2.31.0、CloudWatchエージェント1.300073.0)。
{
"family": "orders-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"volumes": [{ "name": "opentelemetry-auto-instrumentation" }],
"containerDefinitions": [
{
"name": "init",
"image": "public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v2.31.0",
"essential": false,
"command": ["cp", "/javaagent.jar", "/otel-auto-instrumentation/javaagent.jar"],
"mountPoints": [{
"sourceVolume": "opentelemetry-auto-instrumentation",
"containerPath": "/otel-auto-instrumentation",
"readOnly": false
}]
},
{
"name": "ecs-cwagent",
"image": "public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest",
"essential": false,
"secrets": [{ "name": "CW_CONFIG_CONTENT", "valueFrom": "ecs-cwagent" }]
},
{
"name": "app",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/orders-api:1.4.0",
"dependsOn": [{ "containerName": "init", "condition": "SUCCESS" }],
"mountPoints": [{
"sourceVolume": "opentelemetry-auto-instrumentation",
"containerPath": "/otel-auto-instrumentation",
"readOnly": false
}],
"environment": [
{ "name": "OTEL_RESOURCE_ATTRIBUTES", "value": "service.name=orders-api,deployment.environment=prod" },
{ "name": "OTEL_AWS_APPLICATION_SIGNALS_ENABLED", "value": "true" },
{ "name": "OTEL_METRICS_EXPORTER", "value": "none" },
{ "name": "OTEL_LOGS_EXPORTER", "value": "none" },
{ "name": "OTEL_EXPORTER_OTLP_PROTOCOL", "value": "http/protobuf" },
{ "name": "OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT", "value": "http://localhost:4316/v1/metrics" },
{ "name": "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "value": "http://localhost:4316/v1/traces" },
{ "name": "OTEL_TRACES_SAMPLER", "value": "xray" },
{ "name": "OTEL_PROPAGATORS", "value": "tracecontext,baggage,b3,xray" },
{ "name": "JAVA_TOOL_OPTIONS", "value": " -javaagent:/otel-auto-instrumentation/javaagent.jar" }
]
}
]
}
見落としやすいのは2点です。dependsOnのSUCCESS条件が無いと、jarのコピーが終わる前にアプリケーションが起動して-javaagentの読み込みに失敗します。deployment.environmentを省くとECSクラスター名が環境名として使われるので、同じクラスターにステージングと本番を同居させているなら明示してください。実際のタスク定義では、ここで省いたcpu・memory・executionRoleArn・taskRoleArn・ログ設定も必要です。
Python・Node.js・.NETで変わる設定
言語が変わると、initコンテナのイメージとコピー元、アプリケーションにADOTを読み込ませる環境変数が変わります。送信先の4316番とOTEL_AWS_APPLICATION_SIGNALS_ENABLED=trueは共通です。
| 言語 | initのイメージ | コピー元 | 読み込ませる環境変数 |
|---|---|---|---|
| Java | adot-autoinstrumentation-java | /javaagent.jar | JAVA_TOOL_OPTIONS |
| Python | adot-autoinstrumentation-python | /autoinstrumentation/. | PYTHONPATH |
| Node.js | adot-autoinstrumentation-node | /autoinstrumentation/. | NODE_OPTIONS |
| .NET | adot-autoinstrumentation-dotnet | autoinstrumentation/. | CORECLR_*・DOTNET_* |
Pythonは追加の変数が多く、OTEL_PYTHON_DISTRO=aws_distroとOTEL_PYTHON_CONFIGURATOR=aws_configuratorでADOTの設定を使わせ、PYTHONPATHにはADOTの自動計装ディレクトリとアプリケーションの作業ディレクトリの両方を並べます。作業ディレクトリを入れ忘れると、計装以前にアプリケーションが起動しないことがあり、公式のトラブルシューティングにも既知の問題として載っています。Djangoは--noreloadとDJANGO_SETTINGS_MODULEも必要です。
PYTHONPATH=/otel-auto-instrumentation-python/opentelemetry/instrumentation/auto_instrumentation:/app:/otel-auto-instrumentation-python
OTEL_PYTHON_DISTRO=aws_distro
OTEL_PYTHON_CONFIGURATOR=aws_configurator
OTEL_TRACES_SAMPLER=xray
OTEL_TRACES_SAMPLER_ARG=endpoint=http://localhost:2000
Node.jsはNODE_OPTIONS=--require /otel-auto-instrumentation-node/autoinstrumentation.jsで読み込みます。この方法はCommonJS前提で、ESM形式のアプリケーションは別手順になります(後述のEKSの節と同じ制約)。.NETはプロファイラーの仕組みを使うため、CORECLR_ENABLE_PROFILING=1、CORECLR_PROFILER(CLSID)、CORECLR_PROFILER_PATH、DOTNET_STARTUP_HOOKSなどを公式手順どおりに並べます。プロファイラーのパスはLinuxならlinux-x64/OpenTelemetry.AutoInstrumentation.Native.so、Windows Serverならwin-x64/OpenTelemetry.AutoInstrumentation.Native.dllで、Windowsコンテナではinitのコマンドも変わります。
デーモン方式でエンドポイントを書き換える箇所
デーモン方式では、エージェント用のタスク定義(公式例のファミリー名はecs-cwagent-daemon、bridgeモード)を作り、ECSサービスのスケジューリング戦略をDAEMONにしてクラスターに1回だけ配置します。エージェントはホストの4316番と2000番を使うため、同じホストでこの2つのポートを使う別サービスがあると衝突します。
アプリケーション側の変更は送信先だけです。hostモードならサイドカー方式と同じlocalhostのまま動きます。bridgeかawsvpcの場合は、次の3つの変数のlocalhostを、インスタンスメタデータサービス(IMDS)から取ったコンテナインスタンスのプライベートIPに置き換えます。
OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT=http://10.0.12.34:4316/v1/metrics
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://10.0.12.34:4316/v1/traces
OTEL_TRACES_SAMPLER_ARG=endpoint=http://10.0.12.34:2000
タスク定義の環境変数は静的な値なので、インスタンスごとに違うIPを入れるにはエントリポイントでIMDSを引いて書き換えるなどの工夫が要ります。この手間を許容できないなら、サイドカー方式を選ぶ方が運用は単純です。
EKSでの有効化|CloudWatch Observabilityアドオンと注釈
EKSでは、Amazon CloudWatch Observability EKSアドオンがCloudWatchエージェントとADOTの注入の仕組みをまとめて入れます。このアドオンはContainer Insights(拡張オブザーバビリティ)も同時に有効にします。アプリケーション側で書くのは注釈だけです。
アドオンの導入とIAM権限
CloudWatchコンソールの「Application Signals」で「EKS」を選び、対象クラスターを指定すると、アドオンが無ければEKSコンソールでの追加に誘導されます。IAMロールに「ノードから継承」を選んだ場合は、ワーカーノードのロールに次の2つのポリシーを付けます。
aws iam attach-role-policy --role-name my-worker-node-role \
--policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
aws iam attach-role-policy --role-name my-worker-node-role \
--policy-arn arn:aws:iam::aws:policy/AWSXRayWriteOnlyAccess
ノードロールに権限を付けると、PodからIMDSへのアクセスを制限していない限り、そのノードで動くPodが同じ権限を使えてしまいます。アドオンv3.1.0以降では、公式がEKS Pod Identityを推奨しており、cloudwatch-agentサービスアカウントだけにCloudWatchAgentServerPolicy付きのロールを関連付けられます(IRSAも利用可)。なお、WindowsノードではContainer Insightsは動きますが、Application Signalsは対応していません。
Pod注釈と名前空間注釈の書き方
計装は、DeploymentのPodTemplateか、名前空間のメタデータに注釈を付けて有効にします。注釈名は言語ごとに分かれています。
# 抜粋(selector・replicas などは省略)
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
spec:
template:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
# Python: inject-python / Node.js: inject-nodejs / .NET: inject-dotnet
spec:
containers:
- name: orders-api
image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/orders-api:1.4.0
名前空間に付けると、その名前空間の既存と今後のワークロードがすべて対象になります。注釈は次にPodが作られるときに効くので、適用後はkubectl rollout restart deployment -n <名前空間>で再起動します。コンソールの「Console」方式でワークロードを選んだ場合は即座にPodが再起動されるため、本番クラスターでは注釈方式で再起動のタイミングを自分で決める方が安全です。.NETをAlpine Linuxベースのイメージで動かすときは、注釈instrumentation.opentelemetry.io/otel-dotnet-auto-runtime: "linux-musl-x64"を足します。
アドオンv5.0.0以降の自動監視と無効化の設定
アドオン(とHelmチャート)のv5.0.0から、OpenTelemetryベースのAPMがApplication Signals経由で既定で有効になりました。設定のmanager.applicationSignals.autoMonitorにあるmonitorAllServicesの既定値はtrueで、Kubernetes Serviceに紐づくDeployment・DaemonSet・StatefulSetが、新規作成時か次の再起動時に自動で計装されます。kube-systemとamazon-cloudwatchの名前空間は既定で除外されます。
注意したいのは、既にDatadogやNew Relic、自前のOpenTelemetry Collectorで計装しているクラスターでアドオンを更新すると、次の再起動でADOTが注入される点です。公式ドキュメントも、OpenTelemetryベースのAPMを使っている場合は既存の構成に影響すると明記しています。さらに、アプリケーションのコード内に直書きしたOTLPの送信先はアドオンに上書きされることがあり、メトリクスとトレースが本来の送信先に届かなくなります(コンテナの環境変数やenvFromのConfigMapで指定した送信先は上書きされません)。アドオンを更新する前に、詳細設定で次のように無効化しておきます。
{
"manager": {
"applicationSignals": {
"autoMonitor": {
"monitorAllServices": false
}
}
}
}
逆に対象を絞って自動化したい場合は、言語と名前空間を指定します。次はpet-warehouse名前空間のJavaワークロードだけを自動計装し、設定保存時にPodを再起動する例です(restartPodsの既定はfalse)。monitorAllServicesは既定でtrueなので、明示的にfalseにしないと他のサービスも対象に残ります。除外したいワークロードはexcludeに名前空間/Deployment名の形式で書き、除外は対象指定より優先されます。
manager:
applicationSignals:
autoMonitor:
monitorAllServices: false
restartPods: true
customSelector:
java:
namespaces: ["pet-warehouse"]
2026年10月2日時点のHelmチャートの最新はamazon-cloudwatch-observability 6.7.0(2026年9月21日公開)です。
Node.jsのESMアプリケーションの手動計装
ESM形式のNode.jsアプリケーションは、コンソールでの有効化も注釈も効きません。@aws/aws-distro-opentelemetry-node-autoinstrumentationを依存関係に入れ、DockerfileでApplication Signals用の環境変数を設定してイメージを作り直します。このときinject-nodejsの注釈は付けたままにしないよう、公式手順でも注意されています。送信先はクラスター内のエージェントのサービス名cloudwatch-agent.amazon-cloudwatch:4316です。
EKS以外のKubernetesへのHelm導入
EKS以外のKubernetes(EC2上の自前クラスターやオンプレミス)では、アドオンの代わりにHelmチャートでエージェントのオペレーターを入れ、その後は注釈で計装します。clusterNameに指定した名前がダッシュボードに表示されます。オンプレミスの場合は、CloudWatchAgentServerPolicyを付けたIAMユーザーのアクセスキーをクラスターに渡す手順が加わります。
helm repo add aws-observability https://aws-observability.github.io/helm-charts
helm install amazon-cloudwatch-operator aws-observability/amazon-cloudwatch-observability \
--namespace amazon-cloudwatch --create-namespace \
--set region=ap-northeast-1 \
--set clusterName=onprem-k8s-01
EC2・オンプレミスでの有効化|CloudWatchエージェントとADOTの手動導入
EC2とオンプレミスのサーバーでは、CloudWatchエージェントをホストに入れ、アプリケーションの起動コマンドにADOTを組み込みます。Application Signalsに対応するのは2023年11月30日以降に公開されたエージェントなので、古いエージェントが入っているホストは更新が先です。
エージェントの設定は前述の最小構成のJSONを/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.jsonに置き、インスタンスのIAMロールにCloudWatchAgentServerPolicyを付けてから起動します。-cの値にはfile:の接頭辞が必須です。
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config -m ec2 -s \
-c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
JavaはADOT Javaのリリースからaws-opentelemetry-agent.jarを取得し、環境変数を付けて起動します。
JAVA_TOOL_OPTIONS=" -javaagent:/opt/adot/aws-opentelemetry-agent.jar" \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
OTEL_AWS_APPLICATION_SIGNALS_ENABLED=true \
OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT=http://localhost:4316/v1/metrics \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4316/v1/traces \
OTEL_RESOURCE_ATTRIBUTES="service.name=billing-batch,deployment.environment=prod" \
java -jar billing-batch.jar
Pythonはpip install aws-opentelemetry-distro(2026年10月2日時点のPyPI最新は0.20.0、Python 3.10以上)で入れ、opentelemetry-instrument python app.pyの形で起動します。環境変数はECSのPythonと同じくOTEL_PYTHON_DISTROとOTEL_PYTHON_CONFIGURATORが要ります。
オンプレミスのサーバーにはインスタンスロールが無いため、CloudWatchAgentServerPolicyを付けたIAMユーザーを作り、そのアクセスキーをaws configureでホストに設定します。長期のアクセスキーを置くことになるので、キーのローテーションと権限をこのポリシーだけに絞る運用を前提にしてください。
Lambdaでの有効化|コンソール設定と手動・IaCで必要な3項目
Lambdaはエージェントを置かず、ADOTを含むAWS Lambda Layer for OpenTelemetryが計装を担います。Lambdaコンソールなら、関数の「設定」→「モニタリングおよび運用ツール」→「編集」で、Application Signalsによるトレースと標準メトリクスの自動収集にチェックを入れて保存するだけです。CloudWatchコンソールの「Application Signals」から「Lambda」を選び、複数の関数をまとめて有効にすることもできます。
手動やIaCで設定する場合は、レイヤーの追加、環境変数AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument、実行ロールへのCloudWatchLambdaApplicationSignalsExecutionRolePolicyの付与の3点です。既定の計装範囲を広げる環境変数や、コンテナイメージでデプロイした関数にレイヤーの中身を取り込む手順は、Application SignalsのLambda最小構成の解説に載せています。
CDKで有効化するときの注意|ECS用の構成はexperimental
アカウントでの初回有効化は、安定版のaws-cdk-libに含まれるL1リソースCfnDiscoveryで書けます。
import { aws_applicationsignals as applicationsignals } from 'aws-cdk-lib';
new applicationsignals.CfnDiscovery(this, 'ApplicationSignalsDiscovery', {});
ECSのタスク定義にサイドカーとinitコンテナを組み込む作業は、別パッケージ@aws-cdk/aws-applicationsignals-alphaのApplicationSignalsIntegrationがまとめて引き受けます。ただし、このパッケージはREADMEで「experimental」と明示され、将来の版で後方互換の無い変更や削除がありうるとされています(2026年10月2日時点の最新は2.272.0-alpha.0)。
もう一つの落とし穴が、ADOTの版を指定する列挙です。ソースに定義されている版はJavaがV2_10_0、PythonがV0_9_0、Node.jsがV0_6_0、.NETがV1_7_0までで、ADOTの現行版(Java v2.31.0、Python v0.20.0)からかなり遅れています。列挙をそのまま使うと古い計装エージェントで動かすことになります。コンストラクタは公開されているので、版を直接指定できます。指定する版はADOTのリリースノートで変更点を確認してから固定してください。
import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha';
new appsignals.ApplicationSignalsIntegration(this, 'AppSignals', {
taskDefinition: fargateTaskDefinition,
serviceName: 'orders-api',
instrumentation: {
sdkVersion: new appsignals.JavaInstrumentationVersion(
appsignals.JavaInstrumentationVersion.IMAGE_REPO,
'v2.31.0',
appsignals.JavaInstrumentationVersion.DEFAULT_MEMORY_LIMIT_MIB,
),
},
cloudWatchAgentSidecar: {
containerName: 'cloudwatch-agent',
enableLogging: true,
cpu: 256,
memoryLimitMiB: 512,
},
});
experimentalのパッケージをCDKのバージョン更新のたびに追いかける体制が無いなら、本番ではタスク定義をL1や素のJSONで書き、前述の4要素を自分で管理する方を選びます。
データが表示されないときの確認順
有効化してもダッシュボードにサービスが出ない場合、公式のトラブルシューティングは最後の変更から15分待ってから調べるよう求めています。それを過ぎても出ないときは、外側から順に次を確認します。
15分待っても何も出ないときの確認項目
- 検出の有効化:CloudWatchコンソールの「Application Signals」→「サービス」で、手順1が「完了」になっているか。未完了なら「サービスの検出を開始」を実行すると、5分ほどでデータが流れ始める。リージョンごとに必要。
- エージェントの稼働:EKSなら
kubectl -n amazon-cloudwatch get podsで全PodがRunningか。エージェント設定のagentに"debug": trueを足して再起動し、エラーを探す。 - 権限:エージェントのログに
Access Deniedがあれば、導入後にロールのポリシーが外されていないか確認する。 - 計装の注入:EKSでは注釈の値が
"true"か、initコンテナがReadyになっているか。ECSではinitコンテナがSUCCESSで終了しているか。 - 送信の失敗:アプリケーションのログに
Failed to exportが出ていないか。JavaはOTEL_JAVAAGENT_DEBUG=true、PythonはOTEL_PYTHON_LOG_LEVEL=debugで詳細ログを出せる。エージェント側のスロットリングのログも確認する。
UnknownServiceやUnknownRemoteServiceの表示原因
サービス一覧にUnknownServiceが出るのは、OTEL_SERVICE_NAMEもOTEL_RESOURCE_ATTRIBUTESのservice.nameも設定されていないときです。ECSとEC2はサービス名を自動で拾わないので、まずここを疑います。UnknownOperationはリモート呼び出しを起こした操作名が特定できないか、操作名にIDなど値の種類が多すぎる文字列が含まれる場合に出ます。依存先がUnknownRemoteServiceになるのは、計装ライブラリが呼び出し先の種類を判別できない場合で、デプロイの時刻と重なっていないかも確認します。
Gunicorn・uWSGI・Uvicornのワーカーからの未送信
プリフォーク型のサーバーでは、親プロセスで初期化したOpenTelemetry SDKのバックグラウンドスレッドがフォーク後のワーカーに引き継がれず、ワーカーからデータが送られません。対処は2段階で、ワーカー側で計装を初期化したうえで、環境変数OTEL_AWS_PYTHON_DEFER_TO_WORKERS_ENABLED=trueで親プロセスの初期化を飛ばします。Gunicornなら設定ファイルのpost_forkフックで初期化します。
# gunicorn.conf.py
def post_fork(server, worker):
from opentelemetry.instrumentation.auto_instrumentation import sitecustomize
uWSGIはenable-threads = trueとlazy-apps = trueとimport = opentelemetry.instrumentation.auto_instrumentation.sitecustomize、複数ワーカーのUvicornはアプリケーションをimportする前にinitialize()を呼びます。この対処にはADOT PythonとEKSアドオンの最新版が前提です。
よくある質問
Application Signalsとは何ですか?
CloudWatchのAPM機能です。ADOTでアプリケーションを自動計装し、サービスごとのレイテンシー・障害・エラーの指標、サービス間の依存関係、SLOをCloudWatch上で扱えます。料金とSLOの設計はCloudWatch Application Signalsの解説で詳しく説明しています。
ECSのFargateでもApplication Signalsは使えますか?
使えます。ただしサイドカー方式に限られ、ネットワークモードはawsvpcです。デーモン方式はFargateに対応していません。
Lambdaでは何を設定すればApplication Signalsが有効になりますか?
Lambdaコンソールの「モニタリングおよび運用ツール」でApplication Signalsの自動収集にチェックを入れれば有効になります。手動ならレイヤーの追加、AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument、実行ロールへのCloudWatchLambdaApplicationSignalsExecutionRolePolicyの付与の3点です。
EKSで既存のOpenTelemetry計装と共存できますか?
アドオンv5.0.0以降は自動監視が既定で有効なため、そのまま更新すると次の再起動でADOTが注入されます。既存の計装を残したいワークロードは、autoMonitorのmonitorAllServicesをfalseにするか、excludeで外してから更新してください。
Application SignalsでGoやRubyのアプリケーションは計装できますか?
ADOTの自動計装はJava・Python・Node.js・.NETの4言語です。Go・PHP・Rubyは標準のOpenTelemetry SDKで計装し、Transaction Searchを有効にしてトレースを送る構成になります。
関連記事
- Amazon CloudWatch Application Signalsとは|料金・SLO設計・対応言語を実装目線で解説【2026年版】
- AWSオブザーバビリティの実装|ADOT・CloudWatch・Container Insightsで計装する構成【2026年時点】
- AWS X-Rayとは|CloudWatchとの違いとOpenTelemetry移行後の使い方【2026年版】
- Amazon EKSとは?仕組み・ノード提供形態と料金モデル・ECSとの使い分けを実装者目線で解説
- APM(アプリケーション性能監視)とは|仕組み・3種の監視データ・OpenTelemetry計装と導入判断を実装目線で解説