ADOT を使用して Next.js を計測する
kubell Advent Calendar 2024 の投稿です。 [1]
この投稿では、AWS Distro for OpenTelemetry (ADOT) [2] を用いた Next.js の計測について書きます。
TL;DR
- ADOT を使用することで、Next.js アプリケーションにレーシングを実装。特に AWS のサービスを使用している環境では、X-Ray との連携も容易で、運用面でも優れる
- Amplify Gen 2 (Amplify) でホスティングしている Next.js アプリケーションに AWS Distro for OpenTelemetry (ADOT) を導入
- Amazon ECS (ECS) にデプロイした ADOT Collector で X-Ray [3] トレーシングを実現
- バックエンドの計測では Collector を Sidecar として起動可能
- ⚠️ Amplify Managed の制約により、フロントエンドの Tracing とログの紐付けには制限あり
はじめに
本記事では、Amplify でホスティングされている Next.js アプリケーションに、AWS Distro for OpenTelemetry(ADOT)を使用してトレーシング機能を実装する方法について説明します。ADOT は、AWS が提供する OpenTelemetry ディストリビューションで、ECS にデプロイできます。
前提条件と制約事項
- フロントエンドは Amplify Managed で運用されています。
- Amplify の CDN と Render (Lambda) は管理された状態で提供されています。
- Amplify の Lambda の設定は 2024 年 12 月 1 日時点では変更できません。
- この制約により、Tracing とログを紐づけて観察することが困難です。
これらの制約は、特にフロントエンドのパフォーマンス監視やデバッグの際に考慮が必要です。
アーキテクチャ概要
- フロントエンド: Amplify ホスティング
- Server-side Rendering: Lambda
- トレーシング: ADOT
- バックエンド デプロイ環境: ECS
ADOT Collector の設定
ECS でのヘルスチェック設定
ECS でヘルスチェックを行うために、以下のような config.yaml
の設定が必要です。
extensions:
health_check:
endpoint: 0.0.0.0:13133
pprof:
endpoint: 0.0.0.0:1777
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
debug:
verbosity: detailed
awsxray:
region: 'ap-northeast-1'
awsemf:
region: 'ap-northeast-1'
service:
pipelines:
traces:
receivers: [otlp]
exporters: [awsxray]
metrics:
receivers: [otlp]
exporters: [awsemf]
extensions: [pprof, health_check]
telemetry:
logs:
level: debug
ローカル開発環境での設定
ローカルで ADOT を起動する場合、AWS の認証情報が必要です。以下の Docker コマンドで実行できます:
docker run --rm -p 13133:13133 -p 4317:4317 -p 4318:4318 -p 55680:55680 -p 8889:8888 \
-e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" \
-e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" \
-e "AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}" \
-e AWS_REGION=ap-northeast-1 \
--name awscollector public.ecr.aws/aws-observability/aws-otel-collector:latest
必要な IAM Policy
以下の IAM Policy は、ECS タスク定義のタスク実行ロールに必要です。この Policy により、ADOT Collector が X-Ray や CloudWatch と連携できるようになります:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:DescribeLogGroups",
"ssm:GetParameters",
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets",
"xray:GetSamplingStatisticSummaries"
],
"Resource": "*"
}
]
}
- ECS タスク定義でこの Policy をタスク実行ロールにアタッチすることで、ADOT Collector は必要な権限を持って AWS サービスと連携できるようになります。
Next.js アプリケーションでのトレーシング実装
基本実装
Next.js の公式ドキュメント [4] をベースに、実装できます:
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { Resource } from '@opentelemetry/resources'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'next-app',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()
このコードは以下のことを行います:
- OTLP TraceExporter を使用してトレースデータを HTTP で送信。
- リソース名(サービス名)を
next-app
として設定。 - SimpleSpanProcessor を使用してトレースの処理を行う。
カスタマイズのポイント
- Vercel 以外でホスティングする場合は、環境に応じたカスタマイズが必要です。
- Full-Stack TypeScript プロジェクトの場合、トレーシングの実装からテストまでを一貫して行うことが容易です。
ECS での運用について
- バックエンドの場合、OpenTelemetry Collector を Sidecar として起動できます。
- ECS では、ポートマッピングは 1 つで十分です(
localhost
でヘルスチェックが可能なため)
記事は以上です。
この投稿をみていただい方はいいねをお願いします。
それでは次回のアドカレでお会いしましょう👋
-
2024年7月1日、Chatwork株式会社は株式会社kubellへと社名変更しました。 ↩︎
-
https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html ↩︎
-
https://nextjs.org/docs/pages/building-your-application/optimizing/open-telemetry ↩︎
Discussion