
EC2 の OpenTelemetry Collector から API キー(ベアラートークン)で Amazon CloudWatch にトレースを送ってみた
はじめに
2026年11月3日、X-Ray の OTLP トレースエンドポイントで SigV4 に加えて API キー(ベアラートークン)認証がサポートされました。
この記事では、東京リージョンの EC2 上の OpenTelemetry Collector から API キーでトレースを送信し、CloudWatch Logs Insights と X-Ray の取得 API で参照できることを確認しました。
検証環境
| 項目 | 内容 |
|---|---|
| リージョン | ap-northeast-1 |
| EC2 | t3.small、Amazon Linux 2023.12.20261109(x86_64) |
| Collector | otelcol-contrib 0.165.0(GitHub リリースの rpm でインストール) |
| 送信元 | Python 3.9.25、opentelemetry-sdk と opentelemetry-exporter-otlp-proto-http(どちらも 1.41.1) |
| Transaction Search | 検証前から有効。インデックス率は 1%(設定は変更していない) |
設定
IAM ユーザーと API キー
IAM ユーザーを作成して AWSXRayAPIKeyAccess ポリシーをアタッチし、サービス名に xray.amazonaws.com を指定して API キーを発行しました。キーの有効期間は 1 日にしました。
aws iam create-user --user-name xray-traces-api-key-user
aws iam attach-user-policy --user-name xray-traces-api-key-user --policy-arn arn:aws:iam::aws:policy/AWSXRayAPIKeyAccess
aws iam create-service-specific-credential --user-name xray-traces-api-key-user --service-name xray.amazonaws.com --credential-age-days 1
発行手順と必要な権限は、開発者ガイドに書かれています。
EC2 のロール
送信元の EC2 のロールについて、xray:PutTraceSegments と xray:CallWithBearerToken を simulate-principal-policy で評価すると、どちらも implicitDeny でした。
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::<ACCOUNT>:role/xray-apikey-verify-ec2 --action-names xray:PutTraceSegments xray:CallWithBearerToken --query 'EvaluationResults[].[EvalActionName,EvalDecision]'
[
[
"xray:PutTraceSegments",
"implicitDeny"
],
[
"xray:CallWithBearerToken",
"implicitDeny"
]
]
このロールの権限では、X-Ray にトレースを送信できません。
Collector と送信元
発行時の応答にある ServiceCredentialSecret の値を、末尾に改行を付けずに /etc/otelcol-contrib/xray-api-key へ保存しました。権限は 600、所有者は otelcol-contrib ユーザーです。Collector の bearertokenauth 拡張が、このファイルから API キーを読んで Authorization ヘッダーに設定します。
Collector の設定は /etc/otelcol-contrib/config.yaml に保存しました。
extensions:
bearertokenauth:
filename: "/etc/otelcol-contrib/xray-api-key"
receivers:
otlp:
protocols:
http:
endpoint: "127.0.0.1:4318"
processors:
batch:
exporters:
otlp_http/xray:
compression: gzip
traces_endpoint: "https://xray.ap-northeast-1.amazonaws.com/v1/traces"
auth:
authenticator: bearertokenauth
service:
extensions: [bearertokenauth]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp_http/xray]
送信元は、親スパン 1 つと子スパン 3 つを作成し、それぞれに test.run_id 属性を付けて、Collector の 127.0.0.1:4318 へ送る Python スクリプトです。
send_spans.py
import sys
import time
import uuid
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
run_id = sys.argv[1] if len(sys.argv) > 1 else uuid.uuid4().hex[:8]
provider = TracerProvider(resource=Resource.create({"service.name": "apikey-demo"}))
provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter(endpoint="http://127.0.0.1:4318/v1/traces"))
)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("apikey-demo")
with tracer.start_as_current_span("parent-job") as parent:
parent.set_attribute("test.run_id", run_id)
for i in range(3):
with tracer.start_as_current_span(f"child-step-{i}") as child:
child.set_attribute("test.run_id", run_id)
time.sleep(0.05)
provider.shutdown()
print(f"sent run_id={run_id}")
トレースの参照
Logs Insights
1 回目として、test.run_id に run092751 を指定して 1 トレース(4 スパン)を送りました。スパンは CloudWatch Logs の aws/spans ロググループに入り、次のクエリで検索できました。
fields @timestamp, name, spanId, parentSpanId, attributes.test.run_id | filter attributes.test.run_id = 'run092751' | sort @timestamp asc
| name | spanId | parentSpanId |
|---|---|---|
| child-step-0 | bfe4a2e476a8c5d6 | 9a91d3ebc50396e1 |
| child-step-1 | 8c68c514137fa129 | 9a91d3ebc50396e1 |
| child-step-2 | 4ace9b7ce01b29d5 | 9a91d3ebc50396e1 |
| parent-job | 9a91d3ebc50396e1 |
3 つの子スパンの parentSpanId が、parent-job の spanId と一致しています。
続けて、test.run_id を idx-092911 にして 1 トレースずつ 300 回送信し、300 トレース(1200 スパン)を追加しました。Collector の指標は次のとおりです。1204 は、1 回目の 4 スパンと 300 × 4 スパンの合計です。
| 指標 | 値 |
|---|---|
| otelcol_receiver_accepted_spans | 1204 |
| otelcol_exporter_sent_spans | 1204 |
| otelcol_receiver_refused_spans | 0 |
Logs Insights では、次のクエリでスパン数とトレース数を数えました。
filter attributes.test.run_id = 'idx-092911' | stats count(*) as spans, count_distinct(traceId) as traces
送信完了から約 2 分後の時点では spans が 1144 で、1200 に届いていませんでした。約 4 分後に再実行すると、spans が 1200、traces が 300 になりました。
X-Ray の取得 API
get-trace-summaries に --start-time 1794269290 --end-time 1794270790 を指定しました。この範囲には、送った 301 トレース(1 回目の 1 トレースと追加の 300 トレース)が含まれます。返ったのは 4 件でした。約 2 日 17 時間後に同じ範囲で取り直しても 4 件でした。
返った 4 件は、インデックス率 1% の設定と合う数です。
まとめ
X-Ray の OTLP トレースエンドポイントに、API キー(ベアラートークン)認証でトレースを送信できることを確認しました。
AWS 外の環境から X-Ray の OTLP トレースエンドポイントへ送信する場合、AWS 環境でも X-Ray 用の IAM ロールを付けにくい場合、別アカウントの X-Ray へ送りたい場合などに利用できそうです。
API キーを作成する IAM ユーザーには、必要最小限の権限だけを付けてください。可能であれば IP 制限をかけ、ローテーションの準備もしたうえで利用することをおすすめします。









