CloudWatch が OpenTelemetry メトリクスに対応したので試してみた
- CloudWatch が OpenTelemetry メトリクスに対応したので試してみた
はじめに
2026年4月3日、Amazon CloudWatch が OpenTelemetry (OTel) メトリクスの受け入れに対応しました(公開プレビュー)。
Amazon CloudWatch now supports OpenTelemetry metrics in public preview - AWS
これにより、OpenTelemetry Protocol (OTLP) を使ってメトリクスを直接 CloudWatch に送れるようになりました。独自の変換処理や追加の仕組みを用意しなくても、70以上の AWS サービスが出力する標準メトリクスと、自前の OTel メトリクスを PromQL でまとめて問い合わせできます。
同日、Container Insights も OTel メトリクスに対応し、EKS クラスタのメトリクスを OTLP で CloudWatch に送れるようになりました。Kubernetes のメタデータやユーザー定義のラベル(チーム名、アプリ名など)が最大 150 個まで自動付与され、PromQL で柔軟に問い合わせできます。CloudWatch Observability EKS アドオンを使えば、EKS コンソールからワンクリックで導入できます。
Amazon CloudWatch launches OTel Container Insights for Amazon EKS (Preview) - AWS
本記事では、この機能の概要から、設定手順、PromQL による問い合わせ、運用上の工夫、注意点、制約事項、料金まで一通り解説します。
CloudWatch OpenTelemetry メトリクスとは
CloudWatch が OTLP 形式のメトリクスを直接受け取れるようになりました。従来の CloudWatch メトリクスとの大きな違いは、OTel メトリクスが意味のある豊富なラベル(属性)を持っている点です。送信元のサービス情報(リソース属性)、計装ライブラリの情報(計装スコープ)、個々のデータ点の属性といった階層構造をそのまま保ったまま CloudWatch に取り込まれます。
主な特徴
- OTLP の受信口にメトリクスを直接送信できる(変換処理が不要)
- PromQL で自前の OTel メトリクスと AWS 標準メトリクスをまとめて問い合わせ可能
- Query Studio(プレビュー)で PromQL の記述・グラフ表示・アラーム作成・ダッシュボード構築ができる
- CloudWatch の異常検知が OTel メトリクスにも対応
- OTel Enrichment を有効にすると、既存の AWS 標準メトリクスにリソース ARN やタグ情報が付与され、PromQL で問い合わせ可能になる
OpenTelemetry とは
OpenTelemetry は、アプリケーションからメトリクス・ログ・トレースを収集するための、特定の製品に依存しないオープンソースの監視基盤です。CloudWatch は 3 種類のデータすべてに対応しています。
| データ種別 | 問い合わせ方法 |
|---|---|
| メトリクス | PromQL |
| ログ | Logs Insights / LiveTail |
| トレース | Transaction Search |
3 種類のデータが共通の構造と一貫した属性を共有するため、メトリクス・ログ・トレースを横断的に紐づけて、異常の検知から原因の特定までを素早く行えます。
OTel メトリクスで何が変わるのか
標準化によるメリット
従来、アプリケーションの監視データを収集するには、監視先ごとに異なる仕組みを使う必要がありました。CloudWatch に送るなら CloudWatch Agent、Prometheus に送るなら Prometheus のエクスポーター、Datadog なら Datadog Agent…といった具合です。OTel はこの「計装」の部分を標準化します。
- 監視先を変えてもアプリのコードを変えなくていい: OTel SDK でアプリを計装しておけば、送り先を CloudWatch から Prometheus に変えたり、両方に同時に送ったりするのは設定変更だけで済みます。アプリ側のコードには手を入れません。
- チーム間でメトリクスの形式が統一される: マイクロサービスが Java、Python、Go と言語がバラバラでも、OTel SDK を使えば同じ属性名・同じ構造でメトリクスが出力されます。「このチームは
response_timeで、あのチームはlatencyで…」という混乱がなくなります。 - AWS メトリクスと自前メトリクスを同じ PromQL で問い合わせられる: 今回の CloudWatch 対応により、EC2 の CPU 使用率と自前アプリのレイテンシを同じ問い合わせ言語で横断的に分析できます。
標準化によるデメリット
- 学習コストがある: OTel SDK の導入、Collector の設定、PromQL の習得など、既存の CloudWatch メトリクス(
PutMetricDataで送るだけ)と比べると覚えることが多いです。 - 既存の CloudWatch メトリクスとは別の世界: OTel メトリクスは PromQL でしか問い合わせできず、従来の CloudWatch コンソールのメトリクス画面(Metrics Explorer など)では表示されません。運用ツールや既存のアラーム設定との共存を考える必要があります。
- まだプレビュー段階: 東京リージョン未対応、料金体系未確定など、本番環境に入れるにはまだ早い面があります。
属性を持つメトリクスで何ができるか
従来の CloudWatch メトリクスは「メトリクス名 + ディメンション(最大 30 個)」という平坦な構造でした。OTel メトリクスは、1 つのデータ点にリソース属性・計装スコープ・データ点属性という階層的な属性を最大 150 個まで持てます。これにより、以下のような計測・監視が可能になります。
ユースケース 1: サービス × 環境 × リージョンの横断分析
# 本番環境の全サービスのエラー率を、サービス名ごとに集計
sum by ("@resource.service.name")(
{"http.server.errors",
"@resource.deployment.environment"="production"}
)
1 つのメトリクス http.server.errors に「どのサービスか」「どの環境か」「どのリージョンか」が属性として付いているため、1 つの問い合わせで複数の切り口から集計できます。従来なら、サービスごと・環境ごとに別々のカスタムメトリクスを PutMetricData で送る必要がありました。
ユースケース 2: EKS Pod とアプリケーションメトリクスの紐づけ
# 特定サービスの HTTP レイテンシと、そのサービスが動いている Pod の CPU を並べて見る
{"http.server.request.duration",
"@resource.service.name"="order-service",
"@resource.k8s.namespace.name"="production"}
OTel メトリクスにはリソース属性として Kubernetes のネームスペース名、Pod 名、ノード名が自動で付与されるため、「このアプリが遅いのは Pod の CPU が足りないからか?」をメトリクスの属性だけで紐づけて調べられます。
ユースケース 3: AWS 標準メトリクスのタグベース集計
# チームタグ別に Lambda のエラー数を集計
sum by ("@aws.tag.Team")(
{Errors, "@instrumentation.@name"="cloudwatch.aws/lambda"}
)
OTel Enrichment を有効にすると、Lambda 関数に付けた AWS タグ(Team=backend など)が PromQL のラベルとして使えます。「どのチームの Lambda でエラーが多いか」を、関数名を一つずつ指定しなくても集計できます。
ユースケース 4: ハイブリッド環境の統合監視
自社環境の Web サーバーと AWS 上のバックエンドサービスの両方に OTel SDK を入れておけば、同じ形式のメトリクスが CloudWatch に集まります。「自社環境のフロントエンドのレイテンシが上がったのは、AWS 側のバックエンドが遅いからか?」を、1 つの PromQL 問い合わせで確認できます。
構成と送信方法
メトリクスを CloudWatch に送る方法は 3 つあります。それぞれ対応する機能や取り扱えるデータの範囲が異なるため、用途に応じて選択してください。
以下の図は、データの送信元から CloudWatch への流れと、CloudWatch 内での活用方法を示しています。
graph LR
subgraph 送信元
A1[EKS 上のアプリ]
A2[EC2 上のアプリ]
A3[自社環境のアプリ]
end
subgraph 送信方法
B1[OTel Collector]
B2[独自構成の<br/>OTel Collector]
B3[ADOT SDK<br/>Collector なし]
end
subgraph "CloudWatch OTLP 受信口"
C1["monitoring.*.amazonaws.com<br/>/v1/metrics"]
C2["xray.*.amazonaws.com<br/>/v1/traces"]
C3["logs.*.amazonaws.com<br/>/v1/logs"]
end
subgraph "CloudWatch 内の活用"
D1[PromQL で問い合わせ<br/>Query Studio]
D2[アラーム作成]
D3[ダッシュボード]
D4[異常検知]
end
subgraph "AWS 標準メトリクス"
E1[EC2 / Lambda / RDS<br/>など 70 以上のサービス]
end
A1 --> B1
A1 --> B2
A2 --> B2
A2 --> B3
A3 --> B1
A3 --> B3
B1 -->|SigV4 認証<br/>HTTP| C1
B1 -->|SigV4 認証<br/>HTTP| C2
B1 -->|SigV4 認証<br/>HTTP| C3
B2 -->|SigV4 認証<br/>HTTP| C1
B2 -->|SigV4 認証<br/>HTTP| C2
B2 -->|SigV4 認証<br/>HTTP| C3
B3 -->|SigV4 認証<br/>HTTP| C1
B3 -->|SigV4 認証<br/>HTTP| C2
C1 --> D1
E1 -->|OTel Enrichment| D1
D1 --> D2
D1 --> D3
D1 --> D4
| 方法 | Application Signals | 基盤情報の付与 | 実行環境メトリクス | 対応データ |
|---|---|---|---|---|
| OpenTelemetry Collector | ✅ | ❌ | ❌ | ログ, メトリクス, トレース |
| 独自構成の OTel Collector | ✅ | ✅ | ✅ | ログ, メトリクス, トレース |
| ADOT SDK(Collector なし) | ✅ | ✅ | ❌ | メトリクス, トレース |
各列の意味は以下のとおりです。
- Application Signals: サービス間の依存関係の可視化や、アプリケーション性能の監視機能(APM)。OTel SDK が生成するトレース(スパン)をもとに、CloudWatch が「どのサービスがどのサービスを呼んでいるか」「各サービスのレイテンシやエラー率」を自動で分析・可視化してくれます。サービス情報を取得しているのはアプリ側の OTel SDK であり、Collector はスパンを転送するだけなので、3 つの方法すべてで利用できます。
- 基盤情報の付与: メトリクスやトレースのデータ点に、AWS 基盤の情報(EC2 インスタンス ID、EKS クラスタ名、リージョンなど)をラベルとして自動で付け加える機能です。Application Signals が「アプリ層の可視化」なのに対し、こちらは「メトリクスとインフラの紐づけ」です。標準の OpenTelemetry Collector 単体ではこの付与ができないため、AWS 基盤との紐づけが必要な場合は独自構成の Collector か ADOT SDK を選びましょう。
- 実行環境メトリクス: JVM のヒープ使用量やガベージコレクションの回数など、アプリケーションの実行環境自体のメトリクスを収集し、トレースやログと紐づける機能です。これに対応しているのは独自構成の OTel Collector のみです。
- 対応データ: その方法で CloudWatch に送れるデータの種類です。ADOT SDK(Collector なし)ではログの送信に対応していない点に注意してください。
OTel SDK の導入について
上記の 3 つの方法はいずれも、アプリケーションに OTel SDK を組み込むことが前提です。「OTel SDK を入れる」というと大変そうに聞こえますが、自動計装を使えばアプリのソースコードは一切変更しません。
Java の場合は起動オプションに Agent を追加するだけです。
java -javaagent:./aws-opentelemetry-agent.jar -jar my-app.jar
Python の場合はコマンド経由でアプリを起動するだけです。
pip install aws-opentelemetry-distro opentelemetry-instrumentation opentelemetry-instrument python my_app.py
自動計装が Flask、Django、Spring Boot、Express などの主要フレームワークや、requests、boto3、JDBC などのライブラリを自動でフックして、メトリクスやトレースを生成してくれます。
EKS の場合はさらに楽で、CloudWatch Observability EKS アドオンを導入すると、Pod に OTel SDK が自動で注入されるため、アプリの起動方法すら変える必要がありません。
Collector はどこに置くのか
OTel Collector を使う場合、Collector はアプリと同じ環境に配置します。アプリの OTel SDK はデフォルトで localhost:4318 にデータを送り、Collector がそれを受け取って SigV4 署名付きで CloudWatch に転送します。
EC2 の場合は、同じインスタンス上でプロセスとして動かします。
[EC2 インスタンス] ├─ アプリ → localhost:4318 → OTel Collector(プロセス)→ CloudWatch
EKS の場合は、主に 2 つの構成があります。
サイドカー型(Pod ごとに Collector を配置):
[Pod] ├─ アプリコンテナ → localhost:4318 → OTel Collector コンテナ → CloudWatch
デーモン型(ノードごとに Collector を配置):
[Node] ├─ アプリ Pod A ─┐ ├─ アプリ Pod B ──┼→ OTel Collector(DaemonSet)→ CloudWatch ├─ アプリ Pod C ─┘
ADOT SDK(Collector なし)の場合は、Collector を配置する必要がなく、SDK がアプリから直接 CloudWatch に送信します。Collector の運用が不要になる反面、ログの送信には対応していない点に注意してください。
まとめると、手軽に始めたいなら標準の OpenTelemetry Collector、AWS 基盤情報との紐づけや実行環境メトリクスまで含めた完全な構成にしたいなら独自構成の OTel Collector、Collector の運用を省きたいなら ADOT SDK という使い分けになります。
3 つの送信方法の違い
1. OpenTelemetry Collector(標準構成)
OpenTelemetry コミュニティが公式に配布している Collector をそのまま使う方法です。sigv4auth 拡張を組み込んで、OTLP 受信口に SigV4 認証付きで送信します。
- 導入が簡単で、公式リリースをダウンロードするだけで始められる
- ログ・メトリクス・トレースの 3 種類すべてに対応
- ただし、AWS 基盤の情報(どの EC2 で動いているか等)を自動で付与する仕組みは持っていない
- 「まず OTel メトリクスを CloudWatch に送ってみたい」という検証段階に向いている
2. 独自構成の OTel Collector
標準の Collector に AWS 固有のコンポーネント(resourcedetectionprocessor や jmxreceiver など)を追加して自分でビルドする方法です。OpenTelemetry Collector Builder (ocb) を使って必要なモジュールだけを組み合わせます。
- EC2 インスタンス ID、EKS クラスタ名、コンテナ名などの AWS 基盤情報をデータに自動付与できる
- JVM ヒープ使用量やガベージコレクション回数など、実行環境自体のメトリクスも収集してトレースと紐づけられる
- 3 つの方法の中で最も機能が充実しているが、Collector のビルドと運用の手間がかかる
- 本番環境で AWS 基盤との紐づけまで含めた完全な監視を実現したい場合に向いている
3. ADOT SDK(Collector なし)
AWS Distro for OpenTelemetry (ADOT) の SDK をアプリケーションに組み込み、Collector を介さずに直接 OTLP 受信口へ送信する方法です。以下の言語に対応しています。
| 言語 | 自動計装 | 手動計装 | 自動計装の方法 |
|---|---|---|---|
| Java | ✅ | ✅ | -javaagent オプションで Agent を付けるだけ |
| Python | ✅ | ✅ | opentelemetry-instrument コマンドでアプリを起動 |
| Node.js | ✅ | ✅ | --require オプションで読み込み |
| .NET | ✅ | ✅ | NuGet パッケージを追加 |
自動計装を使えば、アプリケーションのコードを変更せずに HTTP リクエストやデータベース呼び出しなどのメトリクス・トレースが自動で収集されます。
- Collector の構築・運用が不要で、環境変数の設定だけで始められる
- AWS 基盤情報(EC2 インスタンス ID、リージョンなど)の自動付与に対応している
- SigV4 署名も IAM ロールから自動取得されるため、認証まわりの実装は不要
- ただし、ログの送信には対応していない(メトリクスとトレースのみ)
- 実行環境メトリクス(JVM メトリクスなど)の収集にも対応していない
- Collector の運用コストを避けたい場合や、メトリクスとトレースだけで十分な場合に向いている
アプリがなくてもインフラ監視はできる
ここまで紹介した 3 つの方法はいずれも「アプリケーションが動いていること」が前提です。OTel SDK をアプリに組み込んで、そのアプリが出すメトリクスやトレースを収集する仕組みだからです。
しかし、「アプリの計装はまだだけど、EC2 の CPU 使用率や Lambda の呼び出し数を PromQL で問い合わせたい」という場合は、OTel SDK も Collector も不要です。OTel Enrichment を有効にするだけで、AWS が自動で収集している標準メトリクス(70 以上のサービス)がそのまま PromQL で問い合わせ可能になります。
つまり、使い方は大きく 2 つに分かれます。
| やりたいこと | 必要なもの |
|---|---|
| AWS インフラのメトリクスを PromQL で問い合わせたい | OTel Enrichment を有効にするだけ(SDK・Collector 不要) |
| 自前アプリのメトリクスも CloudWatch に送りたい | OTel SDK / Collector / ADOT SDK のいずれか |
後述の「実際にやってみる」セクションでは、OTel Enrichment で AWS 標準メトリクスを PromQL で問い合わせるパターンも試しています。
OTLP の受信口
メトリクス用の OTLP 受信口は以下の形式です。
https://monitoring.{リージョン}.amazonaws.com/v1/metrics
例えば、オレゴンリージョンの場合:
https://monitoring.us-west-2.amazonaws.com/v1/metrics
認証には AWS Signature Version 4 (SigV4) を使います。通信は HTTP 1.1 のみ対応で、gRPC には対応していません。
設定手順
前提条件
- OTel SDK / Collector からメトリクスを送信する場合は、送信元の EC2 インスタンスや EKS Pod の IAM ロールに
CloudWatchAgentServerPolicyが付与されていること。自社環境から送る場合は、同等の権限を持つ IAM ユーザーのアクセスキーを設定してください。OTel Enrichment で AWS 標準メトリクスを PromQL で問い合わせるだけなら、この設定は不要です。 - トレースも送る場合は Transaction Search が有効になっていること(メトリクスだけ送る場合は不要)
手順 1: OTel Enrichment の有効化(AWS 標準メトリクスを PromQL で使う場合)
AWS 標準メトリクスを PromQL で問い合わせたい場合は、OTel Enrichment を有効にします。
CloudWatch コンソールの Settings 画面から有効化できます。
- CloudWatch コンソール(https://console.aws.amazon.com/cloudwatch/)を開く
- 左メニューの「Settings」を選択
- Global タブを下にスクロールし、「Enable OTel Enrichment for AWS Metrics」の項目を探す
- 「OTel metric enrichment」のトグルをオンにする



注意: 2026年4月時点で、この項目は us-west-2(オレゴン)では表示されましたが、us-east-1(バージニア)では表示されませんでした。リージョンによってコンソールへの反映状況が異なる可能性があります。AWS CLI では:
aws cloudwatch start-o-tel-enrichment --region us-west-2
また、画面にも記載がありますが、OTel metric enrichment を有効にすると取り込みコストが増加する可能性がある点に注意してください。
複数リージョンで有効にする場合は、リージョンごとに API を呼び出す必要があります。
補足: OTel Enrichment を有効にする前に、アカウントでリソースタグのテレメトリを有効にしておく必要があります。私の環境では「OTel metric enrichment」のトグルをオンにしたタイミングで有効になっていました。

手順 2: OpenTelemetry Collector の設定(メトリクス送信)
OpenTelemetry Collector を使ってメトリクスを CloudWatch に送る設定例です。
receivers: otlp: protocols: http: endpoint: "0.0.0.0:4318" processors: batch: send_batch_size: 200 timeout: 10s exporters: otlphttp: tls: insecure: false endpoint: https://monitoring.us-west-2.amazonaws.com auth: authenticator: sigv4auth extensions: sigv4auth: service: "monitoring" region: "us-west-2" service: extensions: [sigv4auth] pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp]
設定のポイント:
sigv4auth拡張で SigV4 認証を設定serviceは"monitoring"を指定(ログなら"logs"、トレースなら"xray")batch処理でまとめて送る件数と待ち時間を調整
手順 3: ADOT SDK を使った Collector なし送信(Java の例)
Collector を介さず、アプリケーションから直接 OTLP の受信口にメトリクスを送ることもできます。
# ADOT Java Agent の取得 curl -L -O https://github.com/aws-observability/aws-otel-java-instrumentation/releases/latest/download/aws-opentelemetry-agent.jar # 環境変数の設定 export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://monitoring.us-west-2.amazonaws.com/v1/metrics" export OTEL_METRICS_EXPORTER=otlp export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf export OTEL_RESOURCE_ATTRIBUTES="service.name=my-app,deployment.environment=production" export JAVA_TOOL_OPTIONS="-javaagent:./aws-opentelemetry-agent.jar" # アプリケーション起動 java -jar my-app.jar
注意: ADOT Java Agent はバージョン 2.11.2 以降が必要です。
PromQL による問い合わせ
PromQL とは
PromQL(Prometheus Query Language)は、もともと監視ツール Prometheus のために作られた問い合わせ言語です。Prometheus は Kubernetes の監視で広く使われており、PromQL はその中核として「時系列データの選択・集計・変換」を行うために設計されました。
SQL がデータベースの問い合わせ言語であるように、PromQL は時系列メトリクスの問い合わせ言語です。「直近 5 分間の平均 CPU 使用率」「サービス別のエラー率の推移」といった問い合わせを簡潔に書けます。
今回の CloudWatch 対応では、Prometheus 3.0 仕様に基づく PromQL が採用されています。これにより、Prometheus を使い慣れた人はそのままの知識で CloudWatch のメトリクスを問い合わせできますし、Prometheus を別途運用しなくても CloudWatch 上で PromQL が使えるようになりました。
ラベルの構造
OTLP メトリクスが CloudWatch に取り込まれると、階層的なデータ構造が PromQL で扱えるラベルに変換されます。@ 接頭辞で OTLP の階層を区別します。
| OTLP の階層 | フィールド接頭辞 | 属性接頭辞 | 例 |
|---|---|---|---|
| リソース | @resource.@ |
@resource. |
@resource.service.name="myservice" |
| 計装スコープ | @instrumentation.@ |
@instrumentation. |
@instrumentation.@name="otel-go/metrics" |
| データ点 | @datapoint.@ |
@datapoint. または接頭辞なし |
cpu="cpu0" |
| AWS 予約 | N/A | @aws. |
@aws.account_id="123456789" |
Prometheus 3.0 仕様に基づいており、UTF-8 のメトリクス名・ラベル名に対応しています。OTel の命名規約で使われるドット(service.name など)がそのまま使えます。
問い合わせ例
自前の OTel メトリクスの問い合わせ:
# 特定サービスの HTTP 処理中リクエスト数
{"http.server.active_requests", "@resource.service.name"="myservice"}
# US リージョン全体で絞り込み
{"http.server.active_requests",
"@resource.service.name"="myservice",
"@aws.region"=~"us-.*"}
# 5分間の平均値
avg_over_time(
{"http.server.active_requests",
"@resource.service.name"="myservice"}[5m]
)
AWS 標準メトリクスの問い合わせ(OTel Enrichment 有効化後):
# EC2 の CPU 使用率
histogram_avg({CPUUtilization, "@instrumentation.@name"="cloudwatch.aws/ec2"})
# 特定 Lambda 関数の呼び出し回数
histogram_sum({Invocations, FunctionName="my-api-handler"})
# チームタグ別の Lambda エラー数
histogram_sum(
{Errors, "@instrumentation.@name"="cloudwatch.aws/lambda", "@aws.tag.Team"="backend"}
)
# チーム別の Lambda 呼び出し数の合計
sum by ("@aws.tag.Team")(
{Invocations, "@instrumentation.@name"="cloudwatch.aws/lambda"}
)
OTel Enrichment を有効にすると、AWS 標準メトリクスにリソース ARN (cloud.resource_id)、リージョン、アカウント ID、リソースタグが付与されるため、タグを使った集計や絞り込みが可能になります。
Query Studio
Query Studio は CloudWatch コンソール内の対話的な問い合わせ画面です(プレビュー)。
- CloudWatch コンソールを開く
- 左メニューの「Query Studio (Preview)」を選択
- 入力欄のドロップダウンから「PromQL」を選択
- Builder モードでメトリクス名・ラベル・集約関数を選ぶか、Editor モードで PromQL を直接入力
- 「Run」を押して問い合わせを実行



Editor モード

Query Studio からは以下の操作もできます:
- 問い合わせ結果からアラームを直接作成
- グラフをダッシュボードの部品として追加
実際にメトリクスを送って Query Studio で確認してみる
ここまでの説明を踏まえて、実際にメトリクスを送信し、Query Studio で問い合わせてみました。
送信の仕組み
今回は OTel Collector を使わず、Python スクリプトから直接 OTLP 受信口に HTTP POST しています。流れは以下のとおりです。
- OTel の protobuf 定義(
opentelemetry-proto)を使って、メトリクスデータをExportMetricsServiceRequestメッセージとして組み立てる - メッセージを protobuf のバイナリ形式にシリアライズする
- AWS の認証情報(
boto3経由)を使って SigV4 署名を生成し、HTTP ヘッダーに付与する Content-Type: application/x-protobufでhttps://monitoring.us-west-2.amazonaws.com/v1/metricsに POST する
ローカル Mac
└─ Python スクリプト
├─ opentelemetry-proto でメトリクスを組み立て
├─ protobuf にシリアライズ
├─ boto3 で SigV4 署名を生成
└─ HTTP POST → https://monitoring.us-west-2.amazonaws.com/v1/metrics
実際の運用では OTel Collector や ADOT SDK が上記の処理を自動でやってくれるため、ここまで手動で組み立てる必要はありません。今回はあくまで「OTLP 受信口に何が送られているか」を理解するために、あえて低レベルな方法で送信しています。
必要なパッケージは以下の 3 つです。
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http boto3
4 つのパターンで送信し、それぞれ異なるユースケースを想定しています。
パターン 1: 複数サービスからのメトリクス
EC2 や EKS 上で動く 3 つのマイクロサービス(order-service、payment-service、user-service)を想定し、それぞれから以下のメトリクスを送信しました。
| メトリクス名 | 種類 | 内容 |
|---|---|---|
http.server.request.count |
カウンター(累積) | HTTP リクエスト数。ステータスコード 200 と 500 を属性で区別 |
http.server.active_requests |
ゲージ | その時点で処理中のリクエスト数 |
http.server.request.duration |
ヒストグラム | リクエストのレイテンシ分布(バケット: 10/50/100/250/500ms) |
リソース属性として service.name、deployment.environment、host.name を付与しています。これにより、Query Studio で以下のような問い合わせができます。
# サービス別のリクエスト数を集計
sum by ("@resource.service.name")({"http.server.request.count"})

パターン 2: 本番 vs ステージング環境の比較
同じサービス(api-gateway)を本番環境とステージング環境の両方から送信しました。
| 環境 | リクエスト数 | エラー率 |
|---|---|---|
| production | 200 | 15.5% |
| staging | 50 | 45.2% |
deployment.environment 属性で環境を区別しているため、1 つの問い合わせで環境間の比較ができます。
# 環境別のエラー率
{"app.error.rate", "@resource.service.name"="api-gateway"}

パターン 3: Kubernetes メタデータ付きメトリクス
EKS 上の Pod を想定し、Kubernetes 固有のリソース属性を豊富に付与しました。
| リソース属性 | 値 |
|---|---|
k8s.cluster.name |
prod-cluster |
k8s.namespace.name |
ecommerce |
k8s.pod.name |
order-service-7b9f4d6c8-x2k9m |
k8s.node.name |
ip-10-0-1-42.ec2.internal |
k8s.deployment.name |
order-service |
cloud.provider |
aws |
cloud.region |
us-west-2 |
アプリケーションメトリクス(http.server.request.duration)に加えて、Pod レベルのメトリクス(k8s.pod.cpu.utilization、k8s.pod.memory.usage)も送信しています。これにより、「レイテンシが高いのは Pod の CPU が足りないからか?」をメトリクスの属性だけで紐づけて調べられます。
# クラスタ内の Pod CPU 使用率
{"k8s.pod.cpu.utilization", "@resource.k8s.cluster.name"="prod-cluster"}

パターン 4: ハイブリッド環境(自社環境 + AWS)
自社環境のフロントエンド(cloud.provider=on-premises)と AWS 上のバックエンド(cloud.provider=aws)から同じ形式のメトリクスを送信しました。
| 送信元 | サービス名 | 平均レイテンシ |
|---|---|---|
| 自社環境 | frontend-web | 45.2ms |
| AWS | backend-api | 120.8ms |
OTel の標準化により、環境が異なっても同じメトリクス名・同じ属性構造で送れるため、PromQL で横断的に問い合わせできます。
# 環境をまたいだリクエスト数の比較
sum by ("@resource.service.name", "@resource.cloud.provider")({"http.server.request.count"})

送信結果
4 パターンすべて HTTP 200 で送信に成功しました。
=== パターン 1: 複数サービス === → 成功 (HTTP 200, 2093 bytes) === パターン 2: 環境別メトリクス === → 成功 (HTTP 200, 718 bytes) === パターン 3: Kubernetes メタデータ === → 成功 (HTTP 200, 854 bytes) === パターン 4: ハイブリッド環境 === → 成功 (HTTP 200, 974 bytes)
OTel Enrichment で AWS 標準メトリクスを問い合わせてみる
ここまでは自前のメトリクスを送信して Query Studio で確認しましたが、OTel Enrichment を使えばアプリも OTel SDK も入れていない素の EC2 のメトリクスも PromQL で問い合わせできます。
検証用に us-west-2 で t3.micro の EC2 インスタンスを 1 台起動し、以下のタグを付けました。
| タグキー | 値 |
|---|---|
| Name | otel-blog-test |
| Team | platform |
| Environment | test |
5 分ほど待ってから Query Studio で問い合わせてみます。
EC2 の CPU 使用率:
histogram_avg({"CPUUtilization", "@instrumentation.@name"="cloudwatch.aws/ec2"})

タグで絞り込み:
histogram_avg({"CPUUtilization", "@aws.tag.Team"="platform"})

OTel SDK も Collector も入れていない素の EC2 ですが、OTel Enrichment により以下の情報が自動でラベルに付与されていることが確認できます。
ドキュメントによると、OTel Enrichment で付与されるラベルの全量は以下のとおりです(EC2 の場合の例)。
| ラベル | 分類 | 説明 | 値の例 |
|---|---|---|---|
InstanceId |
元のディメンション | CloudWatch の元のディメンションがそのまま残る | i-0940db775c94c9e57 |
@resource.cloud.resource_id |
リソース属性 | リソースの完全な ARN | arn:aws:ec2:us-west-2:...:instance/i-... |
@resource.cloud.provider |
リソース属性 | クラウド種別 | aws |
@resource.cloud.region |
リソース属性 | メトリクスの発生元リージョン | us-west-2 |
@resource.cloud.account.id |
リソース属性 | メトリクスの発生元アカウント ID | 134057437479 |
@instrumentation.@name |
計装スコープ | メトリクスの出元サービスを識別する名前 | cloudwatch.aws/ec2 |
@instrumentation.cloudwatch.source |
計装スコープ | 出元サービスの識別子 | aws.ec2 |
@instrumentation.cloudwatch.solution |
計装スコープ | Enrichment の識別子 | CloudWatchOTelEnrichment |
@aws.tag.* |
AWS タグ | リソースに付けた AWS タグがそのままラベルになる | @aws.tag.Team="platform" |
@aws.account |
システムラベル | メトリクスが取り込まれたアカウント | 134057437479 |
@aws.region |
システムラベル | メトリクスが取り込まれたリージョン | us-west-2 |
ポイントは、AWS タグ(@aws.tag.*)がそのまま PromQL のラベルになる点です。EC2 に Team=platform というタグを付けておけば、@aws.tag.Team="platform" で絞り込めます。タグの設計がそのまま PromQL の問い合わせ設計に直結するため、リソースのタグ付け戦略が重要になります。
つまり、既存の AWS インフラに対しては OTel Enrichment を有効にするだけで、タグベースの PromQL 問い合わせがすぐに使えます。
PromQL アラーム
PromQL の問い合わせを使って CloudWatch アラームを作成できます。
コンソールから作成
- CloudWatch コンソール → 「Alarms」→「Create alarm」
- 「PromQL query」を選択
- PromQL を入力(例:
avg_over_time({"http.server.active_requests"}[5m])) - しきい値・評価間隔・通知先を設定

作成後

Description に Markdown を書けるのが面白いです。

AWS CLI から作成
aws cloudwatch put-metric-alarm \
--alarm-name "HighActiveRequests" \
--alarm-description '## OTel メトリクス監視
処理中リクエスト数が **しきい値を超えた**場合にアラームを発報します。
- 対象: `http.server.active_requests`
- サービス: `myservice`' \
--evaluation-criteria '{
"PromQLCriteria": {
"Query": "{\"http.server.active_requests\", \"@resource.service.name\"=\"myservice\"}",
"PendingPeriod": 300,
"RecoveryPeriod": 300
}
}' \
--evaluation-interval 60 \
--alarm-actions arn:aws:sns:us-west-2:123456789012:my-topic \
--region us-west-2
PromQL アラームでは --threshold や --comparison-operator は指定しません(指定するとエラーになります)。しきい値の判定は PromQL の問い合わせ結果に基づいて行われます。
Query: 評価する PromQL 問い合わせ。結果の各系列がアラームの監視対象になるPendingPeriod: しきい値を超え続けてからアラーム発報するまでの猶予(秒)RecoveryPeriod: しきい値を下回り続けてから復旧するまでの猶予(秒)--evaluation-interval: 問い合わせの評価間隔(秒)。--evaluation-criteriaを使う場合は必須--alarm-description: Markdown 記法に対応しており、コンソール上で見出しや太字、リストが表示される

運用上の工夫
1. まとめ送信の調整
OTel Collector の batch 処理で send_batch_size と timeout を適切に設定しましょう。メトリクスの受信口は 1 回のリクエストで最大 1,000 データ点を受け付けるため、まとめ送信の件数を 200 程度、待ち時間を 10 秒にするのがおすすめです。
2. SigV4 認証の適切な設定
OTLP の受信口は SigV4 認証が必須です。EC2 なら IAM ロール、EKS なら IRSA(IAM Roles for Service Accounts)、自社環境なら IAM ユーザーのアクセスキーを使います。CloudWatchAgentServerPolicy の付与を忘れずに。
3. OTel Enrichment の活用
AWS 標準メトリクスに対して OTel Enrichment を有効にすると、リソース ARN やタグ情報が付与されます。これにより、PromQL でタグを使った集計(チーム別、環境別など)が可能になり、運用の見通しが大幅に良くなります。
4. ラベル設計を意識する
OTel メトリクスのラベル数は 1 データ点あたり最大 150 個、付随情報の合計サイズは最大 40 KB です。不要なラベルを送らないよう、OTel Collector の attributes 処理で取捨選択しましょう。
5. Collector なし構成の検討
単純な構成であれば、ADOT SDK を使って Collector を介さず直接送信するのも選択肢です。ただし、実行環境のメトリクス(JVM メトリクスなど)との紐づけが必要な場合は、独自構成の OTel Collector を使ってください。
6. トレースの取りこぼし防止
トレースを送る場合は、always_on の設定で 100% のスパンを記録し、Application Signals で完全な見通しを確保することが推奨されています。
注意点
Transaction Search の事前有効化が必要
OTLP の受信口を使う前に、CloudWatch の Transaction Search を有効にしておく必要があります。有効にしていない場合、「The OTLP API is supported with CloudWatch Logs as a Trace Segment Destination」というエラーが出ます。
HTTP のみ対応(gRPC 非対応)
CloudWatch の OTLP 受信口は HTTP 1.1 のみ対応で、gRPC には対応していません。OTel Collector や SDK の設定で http/protobuf を指定してください。
プレビュー期間中の制約
OTLP メトリクスの取り込み、PromQL 問い合わせ、OTel Enrichment、Query Studio は公開プレビューであり、仕様が変わる可能性があります。本番環境での利用は慎重に判断してください。
対応リージョンが限られている
2026年4月時点で、以下の 5 リージョンのみ対応しています。東京リージョン(ap-northeast-1)は未対応です。
| リージョン名 | リージョンコード |
|---|---|
| 米国東部(バージニア北部) | us-east-1 |
| 米国西部(オレゴン) | us-west-2 |
| 欧州(アイルランド) | eu-west-1 |
| アジア太平洋(シンガポール) | ap-southeast-1 |
| アジア太平洋(シドニー) | ap-southeast-2 |
ADOT SDK のバージョン要件
ADOT Java Agent はバージョン 2.11.2 以降が必要です。古いバージョンでは OTLP 受信口への直接送信機能が使えません。
認証まわりのよくあるエラー
| エラー | 原因 | 対処法 |
|---|---|---|
| HTTP 403 / security token invalid | AWS 認証情報が無効 | 認証情報を更新する |
| Missing Authentication Token | ADOT で認証ヘッダーが付与されない | ADOT のバージョン確認、認証情報の設定確認 |
| context deadline exceeded | まとめ送信・待ち時間の問題 | batchprocessor の設定を調整 |
| 502 / 503 | 一時的な通信障害 | 再試行の設定を見直す |
制約事項(上限値)
メトリクス受信口の制限
| 項目 | 値 | エラーコード |
|---|---|---|
| 最大リクエスト数 | 500 回/秒/アカウント | 429 |
| 新規系列の作成速度 | 1,000,000 件/10分間 | 429 または 200(一部制限) |
| 最大リクエストサイズ | 1 MB(非圧縮) | 400 |
| 最大データ点数/リクエスト | 1,000 | 400 |
| 最大付随情報サイズ | 40 KB | 400 または 200(一部無効) |
| 最大ラベル数/データ点 | 150 | 400 または 200(一部無効) |
補足: 新規系列の作成速度の制限は、新しいメトリクス名の作成にのみ適用されます。既存メトリクスへのデータ点の追加には適用されません。
PromQL 問い合わせの制限
| 項目 | 値 | エラーコード |
|---|---|---|
| 問い合わせの最大リクエスト数 | 300 回/秒/アカウント | 422 |
| 探索リクエストの最大数 | 10 回/秒/アカウント | 422 |
| 同時問い合わせ数 | 30/アカウント | 429 |
| 同時探索リクエスト数 | 30/アカウント | 429 |
| 問い合わせあたりの最大系列数 | 500 | 200(切り詰め) |
| 探索あたりの最大ラベル数 | 10,000 | 200(切り詰め) |
| 最大問い合わせ範囲 | 7 日間 | 422 |
| 24時間あたりの走査系列数 | 100,000 | 422 |
| 24時間あたりの走査データ点数 | 300,000,000 | 422 |
| 24時間あたりの処理データ点数 | 3,000,000,000 | 422 |
| 実行の制限時間 | 20 秒 | 422 |
料金
プレビュー期間中は無料
2026年4月時点で、以下の機能は公開プレビューであり、無料で利用できます。
- OTLP メトリクスの取り込み
- PromQL 問い合わせ
- OTel Enrichment
- Query Studio
注意: プレビュー終了後は料金体系が変わる可能性があります。正式版の料金については、Amazon CloudWatch Pricing のページを確認してください。
関連する既存の料金
OTel メトリクス自体はプレビュー中無料ですが、以下の関連機能には通常の料金がかかります。
- Transaction Search: トレースを送る場合、Transaction Search の料金が発生
- CloudWatch Logs: OTLP ログを送る場合、ログの取り込み・保管料金が発生
- Application Signals: 有効にしている場合、Application Signals の料金が発生
IAM 権限
メトリクス送信に必要な権限
OTel SDK / Collector からメトリクスを送信する場合、送信元の IAM ロールに CloudWatchAgentServerPolicy 管理ポリシーを付与するのが最も簡単です。OTel Enrichment で AWS 標準メトリクスを PromQL で問い合わせるだけなら、この権限は不要です。
PromQL 問い合わせに必要な権限
| API 操作 | 必要な IAM アクション |
|---|---|
| ExecuteMetricQueryPost / Get | cloudwatch:GetMetricData, cloudwatch:ListMetrics |
| ExecuteMetricRangeQuery / Get | cloudwatch:GetMetricData, cloudwatch:ListMetrics |
| ExecuteMetricSeriesPost / Get | cloudwatch:ListMetrics |
| ExecuteMetricLabelsPost / Get | cloudwatch:ListMetrics |
| ExecuteMetricLabelValuesGet | cloudwatch:ListMetrics |
OTel Enrichment に必要な権限
cloudwatch:StartOTelEnrichment の許可が必要です。
まとめ
CloudWatch の OpenTelemetry メトリクス対応は、AWS の監視・可観測性における大きな前進です。OTLP で直接メトリクスを送れるようになり、PromQL で AWS 標準メトリクスと自前のメトリクスをまとめて問い合わせできるようになったことで、複数環境(EKS、自社基盤、複数アカウント)にまたがる監視がかなり楽になります。
プレビュー期間中は無料で使えるので、対応リージョン(us-east-1 や us-west-2)で試してみるのがおすすめです。ただし、東京リージョンは未対応のため、日本の本番環境で本格的に使うには正式版と東京リージョン対応を待つ必要があります。
参考リンク
- Amazon CloudWatch now supports OpenTelemetry metrics(What's New)
- OpenTelemetry - Amazon CloudWatch(User Guide)
- OTLP Endpoints(User Guide)
- Getting started(User Guide)
- Query metrics with PromQL(User Guide)
- PromQL querying(User Guide)
- Running PromQL queries in Query Studio(User Guide)
- Enabling vended metrics in PromQL(User Guide)
- Troubleshooting(User Guide)
- Amazon CloudWatch Pricing
余談
神奈川県にある塔ノ岳という山に登りました。
大倉バス停という場所から1日に何往復できるか、1年に1回チャレンジしています。
今回は 5 往復して 21 時間弱かかりました。
階段が多いので体力的にも精神的にも鍛えられます。

他:
藤嶌果歩さんが日向坂46 の次のシングルのセンターになって、嬉しいです。
ライブでの彼女の煽りは刺激的で、私の生きる糧になっています。